Skip to content

Commit 0d0e254

Browse files
Junfeng Liautozimu
authored andcommitted
Try handle CompleteDone for CompletionItem with TextEdit.
1 parent 338549a commit 0d0e254

File tree

5 files changed

+90
-70
lines changed

5 files changed

+90
-70
lines changed

autoload/LanguageClient.vim

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -702,6 +702,20 @@ function! LanguageClient#handleCursorMoved() abort
702702
endtry
703703
endfunction
704704

705+
function! LanguageClient#handleCompleteDone()
706+
try
707+
" check if v:completed_item has "text_edit" or "additional_text_edits"
708+
return
709+
710+
call LanguageClient#Notify('languageClient/handleCompleteDone', {
711+
\ 'filename': LSP#filename(),
712+
\ 'completed_item': v:completed_item,
713+
\ })
714+
catch
715+
call s:Debug('LanguageClient caught exception: ' . string(v:exception))
716+
endtry
717+
endfunction
718+
705719
function! s:LanguageClient_FZFSinkLocation(line) abort
706720
return LanguageClient#Notify('LanguageClient_FZFSinkLocation', [a:line])
707721
endfunction

plugin/LanguageClient.vim

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ augroup languageClient
113113
autocmd VimLeavePre * call LanguageClient#exit()
114114
endif
115115

116+
" autocmd CompleteDone * call LanguageClient#handleCompleteDone()
117+
116118
if get(g:, 'LanguageClient_signatureHelpOnCompleteDone', 0)
117119
autocmd CompleteDone *
118120
\ call LanguageClient#textDocument_signatureHelp({}, 's:HandleOutputNothing')

src/languageclient.rs

Lines changed: 19 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,8 +1857,6 @@ impl State {
18571857

18581858
pub fn languageClient_omniComplete(&mut self, params: &Option<Params>) -> Result<Value> {
18591859
info!("Begin {}", REQUEST__OmniComplete);
1860-
let (filename, line, character): (String, u64, u64) =
1861-
self.gather_args(&[VimVar::Filename, VimVar::Line, VimVar::Character], params)?;
18621860
let result = self.textDocument_completion(params)?;
18631861
let result: Option<CompletionResponse> = serde_json::from_value(result)?;
18641862
let result = result.unwrap_or_else(|| CompletionResponse::Array(vec![]));
@@ -1875,74 +1873,12 @@ impl State {
18751873
});
18761874
}
18771875

1878-
let matches: Vec<VimCompleteItem> = matches
1879-
.into_iter()
1880-
.map(|lspitem| self.to_vim_complete_item(&lspitem, &filename, line, character))
1881-
.collect();
1876+
let matches: Result<Vec<VimCompleteItem>> = matches.iter().map(FromLSP::from_lsp).collect();
1877+
let matches = matches?;
18821878
info!("End {}", REQUEST__OmniComplete);
18831879
Ok(serde_json::to_value(matches)?)
18841880
}
18851881

1886-
pub fn to_vim_complete_item(
1887-
&self,
1888-
lspitem: &CompletionItem,
1889-
filename: &str,
1890-
line: u64,
1891-
character: u64,
1892-
) -> VimCompleteItem {
1893-
let mut lines = vec![];
1894-
1895-
let mut abbr = lspitem.label.clone();
1896-
let word = lspitem
1897-
// Try use textEdit.
1898-
.text_edit
1899-
.clone()
1900-
.and_then(|edit| {
1901-
abbr = "".into();
1902-
if lines.is_empty() {
1903-
lines = self.text_documents.get(filename)
1904-
.map_or(vec![], |doc| doc.text.lines().map(std::string::ToString::to_string).collect());
1905-
}
1906-
let next_lines = apply_TextEdits(&lines[..], &[edit]).unwrap_or_default();
1907-
next_lines.get(line as usize)
1908-
.map(|l| l[(character as usize)..].to_string())
1909-
})
1910-
// Or else insertText.
1911-
.or_else(|| lspitem.insert_text.clone())
1912-
// Or else label.
1913-
.unwrap_or_else(|| lspitem.label.clone());
1914-
1915-
let is_snippet;
1916-
let snippet;
1917-
if lspitem.insert_text_format == Some(InsertTextFormat::Snippet) {
1918-
is_snippet = Some(true);
1919-
snippet = word.clone();
1920-
} else {
1921-
is_snippet = None;
1922-
snippet = String::default();
1923-
};
1924-
1925-
let info;
1926-
if let Some(ref doc) = lspitem.documentation {
1927-
info = doc.to_string();
1928-
} else {
1929-
info = "".to_string();
1930-
}
1931-
1932-
VimCompleteItem {
1933-
word,
1934-
abbr,
1935-
icase: 1,
1936-
dup: 1,
1937-
menu: lspitem.detail.clone().unwrap_or_default(),
1938-
info,
1939-
kind: lspitem.kind.map(|k| format!("{:?}", k)).unwrap_or_default(),
1940-
additional_text_edits: lspitem.additional_text_edits.clone(),
1941-
snippet,
1942-
is_snippet,
1943-
}
1944-
}
1945-
19461882
pub fn languageClient_handleBufReadPost(&mut self, params: &Option<Params>) -> Result<()> {
19471883
info!("Begin {}", NOTIFICATION__HandleBufReadPost);
19481884
let (buftype, languageId, filename): (String, String, String) = self.gather_args(
@@ -2077,6 +2013,19 @@ impl State {
20772013
Ok(())
20782014
}
20792015

2016+
pub fn languageClient_handleCompleteDone(&mut self, params: &Option<Params>) -> Result<()> {
2017+
let (filename, completed_item): (String, VimCompleteItem) = self.gather_args(
2018+
&[VimVar::Filename.to_key().as_str(), "completed_item"],
2019+
params,
2020+
)?;
2021+
let text_edit = match completed_item.text_edit {
2022+
Some(text_edit) => text_edit.clone(),
2023+
None => return Ok(()),
2024+
};
2025+
2026+
self.apply_TextEdits(filename, &[text_edit])
2027+
}
2028+
20802029
pub fn languageClient_FZFSinkLocation(&mut self, params: &Option<Params>) -> Result<()> {
20812030
info!("Begin {}", NOTIFICATION__FZFSinkLocation);
20822031
let params = match *params {
@@ -2190,12 +2139,13 @@ impl State {
21902139
CompletionResponse::Array(_) => false,
21912140
CompletionResponse::List(ref list) => list.is_incomplete,
21922141
};
2193-
let matches: Vec<VimCompleteItem> = match result {
2142+
let matches: Result<Vec<VimCompleteItem>> = match result {
21942143
CompletionResponse::Array(arr) => arr,
21952144
CompletionResponse::List(list) => list.items,
2196-
}.into_iter()
2197-
.map(|lspitem| self.to_vim_complete_item(&lspitem, &filename, line, character))
2145+
}.iter()
2146+
.map(FromLSP::from_lsp)
21982147
.collect();
2148+
let matches = matches?;
21992149
self.call::<_, u8>(
22002150
None,
22012151
"cm#complete",

src/rpchandler.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,9 @@ impl State {
163163
NOTIFICATION__HandleCursorMoved => {
164164
self.languageClient_handleCursorMoved(&notification.params)?
165165
}
166+
NOTIFICATION__HandleCompleteDone => {
167+
self.languageClient_handleCompleteDone(&notification.params)?
168+
}
166169
NOTIFICATION__FZFSinkLocation => {
167170
self.languageClient_FZFSinkLocation(&notification.params)?
168171
}

src/types.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub const NOTIFICATION__HandleTextChanged: &str = "languageClient/handleTextChan
2323
pub const NOTIFICATION__HandleBufWritePost: &str = "languageClient/handleBufWritePost";
2424
pub const NOTIFICATION__HandleBufDelete: &str = "languageClient/handleBufDelete";
2525
pub const NOTIFICATION__HandleCursorMoved: &str = "languageClient/handleCursorMoved";
26+
pub const NOTIFICATION__HandleCompleteDone: &str = "languageClient/handleCompleteDone";
2627
pub const NOTIFICATION__FZFSinkLocation: &str = "LanguageClient_FZFSinkLocation";
2728
pub const NOTIFICATION__FZFSinkCommand: &str = "LanguageClient_FZFSinkCommand";
2829
pub const NOTIFICATION__ServerExited: &str = "$languageClient/serverExisted";
@@ -437,7 +438,9 @@ pub struct VimCompleteItem {
437438
pub menu: String,
438439
pub info: String,
439440
pub kind: String,
440-
#[serde(rename = "additionalTextEdits")]
441+
#[serde(skip_serializing_if = "Option::is_none")]
442+
pub text_edit: Option<TextEdit>,
443+
#[serde(rename = "additionalTextEdits", skip_serializing_if = "Option::is_none")]
441444
pub additional_text_edits: Option<Vec<lsp::TextEdit>>,
442445
#[serde(skip_serializing_if = "String::is_empty")]
443446
pub snippet: String,
@@ -902,3 +905,51 @@ impl FromLSP<SymbolInformation> for QuickfixEntry {
902905
})
903906
}
904907
}
908+
909+
impl FromLSP<CompletionItem> for VimCompleteItem {
910+
fn from_lsp(lspitem: &CompletionItem) -> Result<Self> {
911+
let abbr = lspitem.label.clone();
912+
let word = lspitem
913+
.insert_text
914+
.clone()
915+
.unwrap_or_else(|| lspitem.label.clone());
916+
917+
let is_snippet;
918+
let snippet;
919+
if lspitem.insert_text_format == Some(InsertTextFormat::Snippet) {
920+
is_snippet = Some(true);
921+
snippet = word.clone();
922+
} else {
923+
is_snippet = None;
924+
snippet = String::default();
925+
};
926+
927+
let mut info = String::new();
928+
if let Some(ref doc) = lspitem.documentation {
929+
info += &doc.to_string();
930+
}
931+
// if (lspitem.insert_text.is_none() && lspitem.text_edit.is_some())
932+
// || lspitem.additional_text_edits.is_some()
933+
// {
934+
// info += "\n";
935+
// info += &serde_json::to_string(&json!({
936+
// "text_edit": lspitem.text_edit.clone(),
937+
// "additional_text_edits": lspitem.additional_text_edits.clone(),
938+
// }))?;
939+
// }
940+
941+
Ok(VimCompleteItem {
942+
word,
943+
abbr,
944+
icase: 1,
945+
dup: 1,
946+
menu: lspitem.detail.clone().unwrap_or_default(),
947+
info,
948+
kind: lspitem.kind.map(|k| format!("{:?}", k)).unwrap_or_default(),
949+
text_edit: lspitem.text_edit.clone(),
950+
additional_text_edits: lspitem.additional_text_edits.clone(),
951+
snippet,
952+
is_snippet,
953+
})
954+
}
955+
}

0 commit comments

Comments
 (0)