diff options
Diffstat (limited to 'crates/server/src/handlers.rs')
-rw-r--r-- | crates/server/src/handlers.rs | 103 |
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 @@ | |||
1 | use languageserver_types::{Range, Position, Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, SymbolKind}; | 1 | use languageserver_types::{ |
2 | use libsyntax2::SyntaxKind; | 2 | Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, |
3 | Command | ||
4 | }; | ||
3 | use libanalysis::World; | 5 | use libanalysis::World; |
4 | use libeditor::{self, LineIndex, LineCol, TextRange, TextUnit}; | 6 | use libeditor; |
7 | use serde_json::to_value; | ||
5 | 8 | ||
6 | use ::{ | 9 | use ::{ |
7 | req::{self, Decoration}, Result, | 10 | req::{self, Decoration}, Result, |
8 | util::FilePath, | 11 | util::FilePath, |
12 | conv::{Conv, ConvWith}, | ||
9 | }; | 13 | }; |
10 | 14 | ||
11 | pub fn handle_syntax_tree( | 15 | pub 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 | ||
70 | fn to_symbol_kind(kind: SyntaxKind) -> SymbolKind { | 72 | pub 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 | |||
88 | fn 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)] | ||
97 | enum ActionId { | ||
98 | FlipComma | ||
99 | } | ||
100 | |||
101 | impl 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 | |||
114 | fn 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 | |||
121 | fn 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 | |||
131 | fn 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 | |||
138 | fn 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 | } | ||