aboutsummaryrefslogtreecommitdiff
path: root/crates/server/src/main_loop/handlers.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/server/src/main_loop/handlers.rs')
-rw-r--r--crates/server/src/main_loop/handlers.rs137
1 files changed, 137 insertions, 0 deletions
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs
new file mode 100644
index 000000000..c6db22289
--- /dev/null
+++ b/crates/server/src/main_loop/handlers.rs
@@ -0,0 +1,137 @@
1use languageserver_types::{
2 Diagnostic, DiagnosticSeverity, Url, DocumentSymbol,
3 Command
4};
5use libanalysis::World;
6use libeditor;
7use serde_json::to_value;
8
9use ::{
10 req::{self, Decoration}, Result,
11 util::FilePath,
12 conv::{Conv, ConvWith},
13};
14
15pub fn handle_syntax_tree(
16 world: World,
17 params: req::SyntaxTreeParams,
18) -> Result<String> {
19 let path = params.text_document.file_path()?;
20 let file = world.file_syntax(&path)?;
21 Ok(libeditor::syntax_tree(&file))
22}
23
24pub fn handle_extend_selection(
25 world: World,
26 params: req::ExtendSelectionParams,
27) -> Result<req::ExtendSelectionResult> {
28 let path = params.text_document.file_path()?;
29 let file = world.file_syntax(&path)?;
30 let line_index = world.file_line_index(&path)?;
31 let selections = params.selections.into_iter()
32 .map(|r| r.conv_with(&line_index))
33 .map(|r| libeditor::extend_selection(&file, r).unwrap_or(r))
34 .map(|r| r.conv_with(&line_index))
35 .collect();
36 Ok(req::ExtendSelectionResult { selections })
37}
38
39pub fn handle_document_symbol(
40 world: World,
41 params: req::DocumentSymbolParams,
42) -> Result<Option<req::DocumentSymbolResponse>> {
43 let path = params.text_document.file_path()?;
44 let file = world.file_syntax(&path)?;
45 let line_index = world.file_line_index(&path)?;
46
47 let mut res: Vec<DocumentSymbol> = Vec::new();
48
49 for symbol in libeditor::file_symbols(&file) {
50 let doc_symbol = DocumentSymbol {
51 name: symbol.name.clone(),
52 detail: Some(symbol.name),
53 kind: symbol.kind.conv(),
54 deprecated: None,
55 range: symbol.node_range.conv_with(&line_index),
56 selection_range: symbol.name_range.conv_with(&line_index),
57 children: None,
58 };
59 if let Some(idx) = symbol.parent {
60 let children = &mut res[idx].children;
61 if children.is_none() {
62 *children = Some(Vec::new());
63 }
64 children.as_mut().unwrap().push(doc_symbol);
65 } else {
66 res.push(doc_symbol);
67 }
68 }
69 Ok(Some(req::DocumentSymbolResponse::Nested(res)))
70}
71
72pub fn handle_code_action(
73 world: World,
74 params: req::CodeActionParams,
75) -> Result<Option<Vec<Command>>> {
76 let path = params.text_document.file_path()?;
77 let file = world.file_syntax(&path)?;
78 let line_index = world.file_line_index(&path)?;
79 let offset = params.range.conv_with(&line_index).start();
80 let ret = if libeditor::flip_comma(&file, offset).is_some() {
81 Some(vec![apply_code_action_cmd(ActionId::FlipComma)])
82 } else {
83 None
84 };
85 Ok(ret)
86}
87
88fn apply_code_action_cmd(id: ActionId) -> Command {
89 Command {
90 title: id.title().to_string(),
91 command: "apply_code_action".to_string(),
92 arguments: Some(vec![to_value(id).unwrap()]),
93 }
94}
95
96#[derive(Serialize, Deserialize, Clone, Copy)]
97enum ActionId {
98 FlipComma
99}
100
101impl ActionId {
102 fn title(&self) -> &'static str {
103 match *self {
104 ActionId::FlipComma => "Flip `,`",
105 }
106 }
107}
108
109pub fn publish_diagnostics(world: World, uri: Url) -> Result<req::PublishDiagnosticsParams> {
110 let path = uri.file_path()?;
111 let file = world.file_syntax(&path)?;
112 let line_index = world.file_line_index(&path)?;
113 let diagnostics = libeditor::diagnostics(&file)
114 .into_iter()
115 .map(|d| Diagnostic {
116 range: d.range.conv_with(&line_index),
117 severity: Some(DiagnosticSeverity::Error),
118 code: None,
119 source: Some("libsyntax2".to_string()),
120 message: d.msg,
121 related_information: None,
122 }).collect();
123 Ok(req::PublishDiagnosticsParams { uri, diagnostics })
124}
125
126pub fn publish_decorations(world: World, uri: Url) -> Result<req::PublishDecorationsParams> {
127 let path = uri.file_path()?;
128 let file = world.file_syntax(&path)?;
129 let line_index = world.file_line_index(&path)?;
130 let decorations = libeditor::highlight(&file)
131 .into_iter()
132 .map(|h| Decoration {
133 range: h.range.conv_with(&line_index),
134 tag: h.tag,
135 }).collect();
136 Ok(req::PublishDecorationsParams { uri, decorations })
137}