aboutsummaryrefslogtreecommitdiff
path: root/crates/server/src/handlers.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-12 19:02:56 +0100
committerAleksey Kladov <[email protected]>2018-08-12 19:02:56 +0100
commit23c06db9c236db0f9c8ef5117fb1adefd6616c43 (patch)
tree8e265a79b7f8f62761c6ea2dd4fa0d6bc0c74204 /crates/server/src/handlers.rs
parent66be735aa98c32fb062d1c756fa9303ff2d13002 (diff)
Half of code-actions
Diffstat (limited to 'crates/server/src/handlers.rs')
-rw-r--r--crates/server/src/handlers.rs103
1 files changed, 49 insertions, 54 deletions
diff --git a/crates/server/src/handlers.rs b/crates/server/src/handlers.rs
index f6f960d22..c6db22289 100644
--- a/crates/server/src/handlers.rs
+++ b/crates/server/src/handlers.rs
@@ -1,11 +1,15 @@
1use languageserver_types::{Range, Position, Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, SymbolKind}; 1use languageserver_types::{
2use libsyntax2::SyntaxKind; 2 Diagnostic, DiagnosticSeverity, Url, DocumentSymbol,
3 Command
4};
3use libanalysis::World; 5use libanalysis::World;
4use libeditor::{self, LineIndex, LineCol, TextRange, TextUnit}; 6use libeditor;
7use serde_json::to_value;
5 8
6use ::{ 9use ::{
7 req::{self, Decoration}, Result, 10 req::{self, Decoration}, Result,
8 util::FilePath, 11 util::FilePath,
12 conv::{Conv, ConvWith},
9}; 13};
10 14
11pub fn handle_syntax_tree( 15pub fn handle_syntax_tree(
@@ -25,11 +29,9 @@ pub fn handle_extend_selection(
25 let file = world.file_syntax(&path)?; 29 let file = world.file_syntax(&path)?;
26 let line_index = world.file_line_index(&path)?; 30 let line_index = world.file_line_index(&path)?;
27 let selections = params.selections.into_iter() 31 let selections = params.selections.into_iter()
28 .map(|r| { 32 .map(|r| r.conv_with(&line_index))
29 let r = to_text_range(&line_index, r); 33 .map(|r| libeditor::extend_selection(&file, r).unwrap_or(r))
30 let r = libeditor::extend_selection(&file, r).unwrap_or(r); 34 .map(|r| r.conv_with(&line_index))
31 to_vs_range(&line_index, r)
32 })
33 .collect(); 35 .collect();
34 Ok(req::ExtendSelectionResult { selections }) 36 Ok(req::ExtendSelectionResult { selections })
35} 37}
@@ -48,10 +50,10 @@ pub fn handle_document_symbol(
48 let doc_symbol = DocumentSymbol { 50 let doc_symbol = DocumentSymbol {
49 name: symbol.name.clone(), 51 name: symbol.name.clone(),
50 detail: Some(symbol.name), 52 detail: Some(symbol.name),
51 kind: to_symbol_kind(symbol.kind), 53 kind: symbol.kind.conv(),
52 deprecated: None, 54 deprecated: None,
53 range: to_vs_range(&line_index, symbol.node_range), 55 range: symbol.node_range.conv_with(&line_index),
54 selection_range: to_vs_range(&line_index, symbol.name_range), 56 selection_range: symbol.name_range.conv_with(&line_index),
55 children: None, 57 children: None,
56 }; 58 };
57 if let Some(idx) = symbol.parent { 59 if let Some(idx) = symbol.parent {
@@ -67,17 +69,40 @@ pub fn handle_document_symbol(
67 Ok(Some(req::DocumentSymbolResponse::Nested(res))) 69 Ok(Some(req::DocumentSymbolResponse::Nested(res)))
68} 70}
69 71
70fn to_symbol_kind(kind: SyntaxKind) -> SymbolKind { 72pub fn handle_code_action(
71 match kind { 73 world: World,
72 SyntaxKind::FUNCTION => SymbolKind::Function, 74 params: req::CodeActionParams,
73 SyntaxKind::STRUCT => SymbolKind::Struct, 75) -> Result<Option<Vec<Command>>> {
74 SyntaxKind::ENUM => SymbolKind::Enum, 76 let path = params.text_document.file_path()?;
75 SyntaxKind::TRAIT => SymbolKind::Interface, 77 let file = world.file_syntax(&path)?;
76 SyntaxKind::MODULE => SymbolKind::Module, 78 let line_index = world.file_line_index(&path)?;
77 SyntaxKind::TYPE_ITEM => SymbolKind::TypeParameter, 79 let offset = params.range.conv_with(&line_index).start();
78 SyntaxKind::STATIC_ITEM => SymbolKind::Constant, 80 let ret = if libeditor::flip_comma(&file, offset).is_some() {
79 SyntaxKind::CONST_ITEM => SymbolKind::Constant, 81 Some(vec![apply_code_action_cmd(ActionId::FlipComma)])
80 _ => SymbolKind::Variable, 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 }
81 } 106 }
82} 107}
83 108
@@ -88,7 +113,7 @@ pub fn publish_diagnostics(world: World, uri: Url) -> Result<req::PublishDiagnos
88 let diagnostics = libeditor::diagnostics(&file) 113 let diagnostics = libeditor::diagnostics(&file)
89 .into_iter() 114 .into_iter()
90 .map(|d| Diagnostic { 115 .map(|d| Diagnostic {
91 range: to_vs_range(&line_index, d.range), 116 range: d.range.conv_with(&line_index),
92 severity: Some(DiagnosticSeverity::Error), 117 severity: Some(DiagnosticSeverity::Error),
93 code: None, 118 code: None,
94 source: Some("libsyntax2".to_string()), 119 source: Some("libsyntax2".to_string()),
@@ -105,38 +130,8 @@ pub fn publish_decorations(world: World, uri: Url) -> Result<req::PublishDecorat
105 let decorations = libeditor::highlight(&file) 130 let decorations = libeditor::highlight(&file)
106 .into_iter() 131 .into_iter()
107 .map(|h| Decoration { 132 .map(|h| Decoration {
108 range: to_vs_range(&line_index, h.range), 133 range: h.range.conv_with(&line_index),
109 tag: h.tag, 134 tag: h.tag,
110 }).collect(); 135 }).collect();
111 Ok(req::PublishDecorationsParams { uri, decorations }) 136 Ok(req::PublishDecorationsParams { uri, decorations })
112} 137}
113
114fn to_text_range(line_index: &LineIndex, range: Range) -> TextRange {
115 TextRange::from_to(
116 to_text_unit(line_index, range.start),
117 to_text_unit(line_index, range.end),
118 )
119}
120
121fn to_text_unit(line_index: &LineIndex, position: Position) -> TextUnit {
122 // TODO: UTF-16
123 let line_col = LineCol {
124 line: position.line as u32,
125 col: (position.character as u32).into(),
126 };
127 line_index.offset(line_col)
128}
129
130
131fn to_vs_range(line_index: &LineIndex, range: TextRange) -> Range {
132 Range::new(
133 to_vs_position(line_index, range.start()),
134 to_vs_position(line_index, range.end()),
135 )
136}
137
138fn to_vs_position(line_index: &LineIndex, offset: TextUnit) -> Position {
139 let line_col = line_index.line_col(offset);
140 // TODO: UTF-16
141 Position::new(line_col.line as u64, u32::from(line_col.col) as u64)
142}