diff options
-rw-r--r-- | crates/libeditor/src/scope.rs | 14 | ||||
-rw-r--r-- | crates/libeditor/tests/test.rs | 8 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/generated.rs | 8 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar.ron | 6 | ||||
-rw-r--r-- | crates/server/src/main_loop/handlers.rs | 50 | ||||
-rw-r--r-- | crates/server/src/main_loop/mod.rs | 4 | ||||
-rw-r--r-- | crates/server/src/req.rs | 27 |
7 files changed, 115 insertions, 2 deletions
diff --git a/crates/libeditor/src/scope.rs b/crates/libeditor/src/scope.rs index 76104b2cf..3d398a74c 100644 --- a/crates/libeditor/src/scope.rs +++ b/crates/libeditor/src/scope.rs | |||
@@ -61,7 +61,19 @@ fn compute_expr_scopes(expr: ast::Expr, scopes: &mut FnScopes, scope: ScopeId) { | |||
61 | compute_block_scopes(block, scopes, scope); | 61 | compute_block_scopes(block, scopes, scope); |
62 | } | 62 | } |
63 | } | 63 | } |
64 | // ForExpr(e) => TODO, | 64 | ast::Expr::ForExpr(e) => { |
65 | if let Some(expr) = e.iterable() { | ||
66 | compute_expr_scopes(expr, scopes, scope); | ||
67 | } | ||
68 | let mut scope = scope; | ||
69 | if let Some(pat) = e.pat() { | ||
70 | scope = scopes.new_scope(scope); | ||
71 | scopes.add_bindings(scope, pat); | ||
72 | } | ||
73 | if let Some(block) = e.body() { | ||
74 | compute_block_scopes(block, scopes, scope); | ||
75 | } | ||
76 | }, | ||
65 | _ => { | 77 | _ => { |
66 | expr.syntax().children() | 78 | expr.syntax().children() |
67 | .filter_map(ast::Expr::cast) | 79 | .filter_map(ast::Expr::cast) |
diff --git a/crates/libeditor/tests/test.rs b/crates/libeditor/tests/test.rs index d051980b0..d8c24610d 100644 --- a/crates/libeditor/tests/test.rs +++ b/crates/libeditor/tests/test.rs | |||
@@ -286,6 +286,14 @@ fn quux() { | |||
286 | } | 286 | } |
287 | ", r#"[CompletionItem { name: "b" }, | 287 | ", r#"[CompletionItem { name: "b" }, |
288 | CompletionItem { name: "a" }]"#); | 288 | CompletionItem { name: "a" }]"#); |
289 | |||
290 | do_check(r" | ||
291 | fn quux() { | ||
292 | for x in &[1, 2, 3] { | ||
293 | <|> | ||
294 | } | ||
295 | } | ||
296 | ", r#"[CompletionItem { name: "x" }]"#); | ||
289 | } | 297 | } |
290 | 298 | ||
291 | fn file(text: &str) -> File { | 299 | fn file(text: &str) -> File { |
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index 6891e857c..f99d1274a 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs | |||
@@ -539,6 +539,14 @@ impl<'a> AstNode<'a> for ForExpr<'a> { | |||
539 | } | 539 | } |
540 | 540 | ||
541 | impl<'a> ForExpr<'a> { | 541 | impl<'a> ForExpr<'a> { |
542 | pub fn pat(self) -> Option<Pat<'a>> { | ||
543 | super::child_opt(self) | ||
544 | } | ||
545 | |||
546 | pub fn iterable(self) -> Option<Expr<'a>> { | ||
547 | super::child_opt(self) | ||
548 | } | ||
549 | |||
542 | pub fn body(self) -> Option<Block<'a>> { | 550 | pub fn body(self) -> Option<Block<'a>> { |
543 | super::child_opt(self) | 551 | super::child_opt(self) |
544 | } | 552 | } |
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index c9e128462..a98e9e2fd 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron | |||
@@ -344,7 +344,11 @@ Grammar( | |||
344 | options: [ ["body", "Block"] ] | 344 | options: [ ["body", "Block"] ] |
345 | ), | 345 | ), |
346 | "ForExpr": ( | 346 | "ForExpr": ( |
347 | options: [ ["body", "Block"] ] | 347 | options: [ |
348 | ["pat", "Pat"], | ||
349 | ["iterable", "Expr"], | ||
350 | ["body", "Block"] , | ||
351 | ] | ||
348 | ), | 352 | ), |
349 | "WhileExpr": ( | 353 | "WhileExpr": ( |
350 | options: [ | 354 | options: [ |
diff --git a/crates/server/src/main_loop/handlers.rs b/crates/server/src/main_loop/handlers.rs index 350eda7df..583af0900 100644 --- a/crates/server/src/main_loop/handlers.rs +++ b/crates/server/src/main_loop/handlers.rs | |||
@@ -204,6 +204,56 @@ pub fn handle_code_action( | |||
204 | return Ok(Some(res)); | 204 | return Ok(Some(res)); |
205 | } | 205 | } |
206 | 206 | ||
207 | pub fn handle_runnables( | ||
208 | world: ServerWorld, | ||
209 | params: req::RunnablesParams, | ||
210 | ) -> Result<Vec<req::Runnable>> { | ||
211 | let file_id = params.text_document.try_conv_with(&world)?; | ||
212 | let file = world.analysis().file_syntax(file_id)?; | ||
213 | let line_index = world.analysis().file_line_index(file_id)?; | ||
214 | let offset = params.position.map(|it| it.conv_with(&line_index)); | ||
215 | let mut res = Vec::new(); | ||
216 | for runnable in libeditor::runnables(&file) { | ||
217 | if let Some(offset) = offset { | ||
218 | if !contains_offset_nonstrict(runnable.range, offset) { | ||
219 | continue; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | let r = req::Runnable { | ||
224 | range: runnable.range.conv_with(&line_index), | ||
225 | label: match &runnable.kind { | ||
226 | libeditor::RunnableKind::Test { name } => | ||
227 | format!("test {}", name), | ||
228 | libeditor::RunnableKind::Bin => | ||
229 | "run binary".to_string(), | ||
230 | }, | ||
231 | bin: "cargo".to_string(), | ||
232 | args: match runnable.kind { | ||
233 | libeditor::RunnableKind::Test { name } => { | ||
234 | vec![ | ||
235 | "test".to_string(), | ||
236 | "--".to_string(), | ||
237 | name, | ||
238 | "--nocapture".to_string(), | ||
239 | ] | ||
240 | } | ||
241 | libeditor::RunnableKind::Bin => vec!["run".to_string()] | ||
242 | }, | ||
243 | env: { | ||
244 | let mut m = HashMap::new(); | ||
245 | m.insert( | ||
246 | "RUST_BACKTRACE".to_string(), | ||
247 | "short".to_string(), | ||
248 | ); | ||
249 | m | ||
250 | } | ||
251 | }; | ||
252 | res.push(r); | ||
253 | } | ||
254 | return Ok(res); | ||
255 | } | ||
256 | |||
207 | pub fn handle_workspace_symbol( | 257 | pub fn handle_workspace_symbol( |
208 | world: ServerWorld, | 258 | world: ServerWorld, |
209 | params: req::WorkspaceSymbolParams, | 259 | params: req::WorkspaceSymbolParams, |
diff --git a/crates/server/src/main_loop/mod.rs b/crates/server/src/main_loop/mod.rs index 5213ecc04..6d6ca6ae9 100644 --- a/crates/server/src/main_loop/mod.rs +++ b/crates/server/src/main_loop/mod.rs | |||
@@ -29,6 +29,7 @@ use { | |||
29 | handle_parent_module, | 29 | handle_parent_module, |
30 | handle_join_lines, | 30 | handle_join_lines, |
31 | handle_completion, | 31 | handle_completion, |
32 | handle_runnables, | ||
32 | }, | 33 | }, |
33 | }; | 34 | }; |
34 | 35 | ||
@@ -138,6 +139,9 @@ fn on_request( | |||
138 | handle_request_on_threadpool::<req::CodeActionRequest>( | 139 | handle_request_on_threadpool::<req::CodeActionRequest>( |
139 | &mut req, pool, world, sender, handle_code_action, | 140 | &mut req, pool, world, sender, handle_code_action, |
140 | )?; | 141 | )?; |
142 | handle_request_on_threadpool::<req::Runnables>( | ||
143 | &mut req, pool, world, sender, handle_runnables, | ||
144 | )?; | ||
141 | handle_request_on_threadpool::<req::WorkspaceSymbol>( | 145 | handle_request_on_threadpool::<req::WorkspaceSymbol>( |
142 | &mut req, pool, world, sender, handle_workspace_symbol, | 146 | &mut req, pool, world, sender, handle_workspace_symbol, |
143 | )?; | 147 | )?; |
diff --git a/crates/server/src/req.rs b/crates/server/src/req.rs index 6d3466b66..e4138abba 100644 --- a/crates/server/src/req.rs +++ b/crates/server/src/req.rs | |||
@@ -1,3 +1,5 @@ | |||
1 | use std::collections::HashMap; | ||
2 | |||
1 | use serde::{ser::Serialize, de::DeserializeOwned}; | 3 | use serde::{ser::Serialize, de::DeserializeOwned}; |
2 | use languageserver_types::{TextDocumentIdentifier, Range, Url, Position, Location}; | 4 | use languageserver_types::{TextDocumentIdentifier, Range, Url, Position, Location}; |
3 | use url_serde; | 5 | use url_serde; |
@@ -134,3 +136,28 @@ pub struct JoinLinesParams { | |||
134 | pub text_document: TextDocumentIdentifier, | 136 | pub text_document: TextDocumentIdentifier, |
135 | pub range: Range, | 137 | pub range: Range, |
136 | } | 138 | } |
139 | |||
140 | pub enum Runnables {} | ||
141 | |||
142 | impl Request for Runnables { | ||
143 | type Params = RunnablesParams; | ||
144 | type Result = Vec<Runnable>; | ||
145 | const METHOD: &'static str = "m/joinLines"; | ||
146 | } | ||
147 | |||
148 | #[derive(Deserialize, Debug)] | ||
149 | #[serde(rename_all = "camelCase")] | ||
150 | pub struct RunnablesParams { | ||
151 | pub text_document: TextDocumentIdentifier, | ||
152 | pub position: Option<Position>, | ||
153 | } | ||
154 | |||
155 | #[derive(Serialize, Debug)] | ||
156 | #[serde(rename_all = "camelCase")] | ||
157 | pub struct Runnable { | ||
158 | pub range: Range, | ||
159 | pub label: String, | ||
160 | pub bin: String, | ||
161 | pub args: Vec<String>, | ||
162 | pub env: HashMap<String, String>, | ||
163 | } | ||