lsp_core/feature/
completion.rs1use bevy_ecs::{prelude::*, schedule::ScheduleLabel};
2use derive_more::{AsMut, AsRef, Deref, DerefMut};
3use lsp_types::{
4 CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionTextEdit,
5 Documentation, InsertTextFormat, TextEdit,
6};
7
8pub use crate::{
9 systems::{
10 complete_class, complete_properties, keyword_complete, prefix::defined_prefix_completion,
11 },
12 util::{token::get_current_token, triple::get_current_triple},
13};
14
15#[derive(ScheduleLabel, Clone, Eq, PartialEq, Debug, Hash)]
17pub struct Label;
18
19#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
21pub struct CompletionRequest(pub Vec<SimpleCompletion>);
22
23pub fn setup_schedule(world: &mut World) {
24 let mut completion = Schedule::new(Label);
25 completion.add_systems((
26 get_current_token,
27 keyword_complete.after(get_current_token),
28 get_current_triple.after(get_current_token),
29 complete_class.after(get_current_triple),
30 complete_properties.after(get_current_triple),
31 defined_prefix_completion.after(get_current_token),
32 ));
33 world.add_schedule(completion);
34}
35
36#[derive(Debug)]
37pub struct SimpleCompletion {
38 pub kind: CompletionItemKind,
39 pub label: String,
40 pub _label_details: Option<CompletionItemLabelDetails>,
41 pub _documentation: Option<String>,
42 pub _sort_text: Option<String>,
43 pub _filter_text: Option<String>,
44 pub edits: Vec<TextEdit>,
45 pub _commit_char: Option<String>,
46}
47
48impl SimpleCompletion {
49 pub fn new(kind: CompletionItemKind, label: String, edit: TextEdit) -> Self {
50 Self {
51 kind,
52 label,
53 edits: vec![edit],
54 _label_details: None,
55 _documentation: None,
56 _sort_text: None,
57 _filter_text: None,
58 _commit_char: None,
59 }
60 }
61
62 pub fn label_detail(mut self, detail: impl Into<String>) -> Self {
63 if let Some(ref mut t) = self._label_details {
64 t.detail = Some(detail.into());
65 } else {
66 self._label_details = Some(CompletionItemLabelDetails {
67 detail: Some(detail.into()),
68 description: None,
69 });
70 }
71
72 self
73 }
74
75 pub fn label_description(mut self, description: impl Into<String>) -> Self {
76 if let Some(ref mut t) = self._label_details {
77 t.description = Some(description.into());
78 } else {
79 self._label_details = Some(CompletionItemLabelDetails {
80 description: Some(description.into()),
81 detail: None,
82 });
83 }
84
85 self
86 }
87
88 pub fn text_edit(mut self, edit: TextEdit) -> Self {
89 self.edits.push(edit);
90 self
91 }
92
93 pub fn documentation(mut self, documentation: impl Into<String>) -> Self {
94 self._documentation = Some(documentation.into());
95 self
96 }
97
98 pub fn m_documentation<S: Into<String>>(mut self, documentation: Option<S>) -> Self {
99 self._documentation = documentation.map(|x| x.into());
100 self
101 }
102
103 pub fn sort_text(mut self, sort_text: impl Into<String>) -> Self {
104 self._sort_text = Some(sort_text.into());
105 self
106 }
107
108 pub fn filter_text(mut self, filter_text: impl Into<String>) -> Self {
109 self._filter_text = Some(filter_text.into());
110 self
111 }
112
113 pub fn commit_char(mut self, commit_char: impl Into<String>) -> Self {
114 self._commit_char = Some(commit_char.into());
115 self
116 }
117}
118
119impl Into<CompletionItem> for SimpleCompletion {
120 fn into(self) -> CompletionItem {
121 let SimpleCompletion {
122 _filter_text: filter_text,
123 _sort_text: sort_text,
124 label,
125 _label_details,
126 _documentation: documentation,
127 kind,
128 edits,
129 _commit_char: commit_char,
130 } = self;
131
132 let text_edit = edits
133 .iter()
134 .next()
135 .map(|x| CompletionTextEdit::Edit(x.clone()));
136
137 let additional_text_edits = edits.into_iter().skip(1).collect();
138
139 CompletionItem {
140 label,
141 kind: Some(kind),
142 sort_text,
143 insert_text_format: (kind == CompletionItemKind::SNIPPET)
144 .then_some(InsertTextFormat::SNIPPET),
145 filter_text,
146 label_details: _label_details,
147 documentation: documentation.map(|st| Documentation::String(st)),
148 text_edit,
149 additional_text_edits: Some(additional_text_edits),
150 commit_characters: commit_char.map(|x| vec![String::from(x)]),
151 ..Default::default()
152 }
153 }
154}