diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-09-26 20:31:28 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2019-09-26 20:31:28 +0100 |
commit | 1002e470747fe5887a2915689e21d9be3a1ca5d8 (patch) | |
tree | 3fd5903b67b498a39660b2dafdc929f33d41900e /crates | |
parent | 53a30d9e69ee5149e4fdb1c6fe4081281e879d0e (diff) | |
parent | d847d53e36571c8f7925b72cedf66bb203976148 (diff) |
Merge #1921
1921: WIP: start simplifying editing API r=matklad a=matklad
Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/assists/add_missing_impl_members.rs | 8 | ||||
-rw-r--r-- | crates/ra_assists/src/assists/auto_import.rs | 1 | ||||
-rw-r--r-- | crates/ra_assists/src/ast_editor.rs | 72 | ||||
-rw-r--r-- | crates/ra_assists/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_api/src/line_index.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_api/src/runnables.rs | 1 | ||||
-rw-r--r-- | crates/ra_lsp_server/src/markdown.rs | 1 | ||||
-rw-r--r-- | crates/ra_parser/src/grammar.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/edit.rs | 52 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 48 |
12 files changed, 107 insertions, 82 deletions
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs index 23da1e65f..682455bce 100644 --- a/crates/ra_assists/src/assists/add_missing_impl_members.rs +++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs | |||
@@ -100,12 +100,11 @@ fn strip_docstring(item: ast::ImplItem) -> ast::ImplItem { | |||
100 | } | 100 | } |
101 | 101 | ||
102 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { | 102 | fn add_body(fn_def: ast::FnDef) -> ast::FnDef { |
103 | let mut ast_editor = AstEditor::new(fn_def.clone()); | ||
104 | if fn_def.body().is_none() { | 103 | if fn_def.body().is_none() { |
105 | let body = make::block_from_expr(make::expr_unimplemented()); | 104 | fn_def.with_body(make::block_from_expr(make::expr_unimplemented())) |
106 | ast_editor.set_body(&body); | 105 | } else { |
106 | fn_def | ||
107 | } | 107 | } |
108 | ast_editor.ast().to_owned() | ||
109 | } | 108 | } |
110 | 109 | ||
111 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being | 110 | /// Given an `ast::ImplBlock`, resolves the target trait (the one being |
@@ -332,5 +331,4 @@ impl Foo for S { | |||
332 | }", | 331 | }", |
333 | ) | 332 | ) |
334 | } | 333 | } |
335 | |||
336 | } | 334 | } |
diff --git a/crates/ra_assists/src/assists/auto_import.rs b/crates/ra_assists/src/assists/auto_import.rs index 5aae98546..a91c170b9 100644 --- a/crates/ra_assists/src/assists/auto_import.rs +++ b/crates/ra_assists/src/assists/auto_import.rs | |||
@@ -448,7 +448,6 @@ fn make_assist_add_in_tree_list( | |||
448 | fmt_segments_raw(target, &mut buf); | 448 | fmt_segments_raw(target, &mut buf); |
449 | edit.insert(offset, buf); | 449 | edit.insert(offset, buf); |
450 | } else { | 450 | } else { |
451 | |||
452 | } | 451 | } |
453 | } | 452 | } |
454 | 453 | ||
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs index 2a685f26e..72c8c478a 100644 --- a/crates/ra_assists/src/ast_editor.rs +++ b/crates/ra_assists/src/ast_editor.rs | |||
@@ -6,7 +6,7 @@ use rustc_hash::FxHashMap; | |||
6 | use ra_fmt::leading_indent; | 6 | use ra_fmt::leading_indent; |
7 | use ra_syntax::{ | 7 | use ra_syntax::{ |
8 | algo, | 8 | algo, |
9 | ast::{self, TypeBoundsOwner}, | 9 | ast::{self, make::tokens, TypeBoundsOwner}, |
10 | AstNode, Direction, InsertPosition, SyntaxElement, | 10 | AstNode, Direction, InsertPosition, SyntaxElement, |
11 | SyntaxKind::*, | 11 | SyntaxKind::*, |
12 | T, | 12 | T, |
@@ -229,26 +229,6 @@ impl AstEditor<ast::ImplItem> { | |||
229 | } | 229 | } |
230 | } | 230 | } |
231 | 231 | ||
232 | impl AstEditor<ast::FnDef> { | ||
233 | pub fn set_body(&mut self, body: &ast::Block) { | ||
234 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | ||
235 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.ast().body() { | ||
236 | old_body.syntax().clone().into() | ||
237 | } else if let Some(semi) = self.ast().semicolon_token() { | ||
238 | to_insert.push(tokens::single_space().into()); | ||
239 | semi.into() | ||
240 | } else { | ||
241 | to_insert.push(tokens::single_space().into()); | ||
242 | to_insert.push(body.syntax().clone().into()); | ||
243 | self.ast = self.insert_children(InsertPosition::Last, to_insert.into_iter()); | ||
244 | return; | ||
245 | }; | ||
246 | to_insert.push(body.syntax().clone().into()); | ||
247 | let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi); | ||
248 | self.ast = self.replace_children(replace_range, to_insert.into_iter()) | ||
249 | } | ||
250 | } | ||
251 | |||
252 | impl AstEditor<ast::TypeParam> { | 232 | impl AstEditor<ast::TypeParam> { |
253 | pub fn remove_bounds(&mut self) -> &mut Self { | 233 | pub fn remove_bounds(&mut self) -> &mut Self { |
254 | let colon = match self.ast.colon_token() { | 234 | let colon = match self.ast.colon_token() { |
@@ -263,53 +243,3 @@ impl AstEditor<ast::TypeParam> { | |||
263 | self | 243 | self |
264 | } | 244 | } |
265 | } | 245 | } |
266 | |||
267 | mod tokens { | ||
268 | use once_cell::sync::Lazy; | ||
269 | use ra_syntax::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; | ||
270 | |||
271 | static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;")); | ||
272 | |||
273 | pub(crate) fn comma() -> SyntaxToken { | ||
274 | SOURCE_FILE | ||
275 | .tree() | ||
276 | .syntax() | ||
277 | .descendants_with_tokens() | ||
278 | .filter_map(|it| it.into_token()) | ||
279 | .find(|it| it.kind() == T![,]) | ||
280 | .unwrap() | ||
281 | } | ||
282 | |||
283 | pub(crate) fn single_space() -> SyntaxToken { | ||
284 | SOURCE_FILE | ||
285 | .tree() | ||
286 | .syntax() | ||
287 | .descendants_with_tokens() | ||
288 | .filter_map(|it| it.into_token()) | ||
289 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") | ||
290 | .unwrap() | ||
291 | } | ||
292 | |||
293 | #[allow(unused)] | ||
294 | pub(crate) fn single_newline() -> SyntaxToken { | ||
295 | SOURCE_FILE | ||
296 | .tree() | ||
297 | .syntax() | ||
298 | .descendants_with_tokens() | ||
299 | .filter_map(|it| it.into_token()) | ||
300 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") | ||
301 | .unwrap() | ||
302 | } | ||
303 | |||
304 | pub(crate) struct WsBuilder(SourceFile); | ||
305 | |||
306 | impl WsBuilder { | ||
307 | pub(crate) fn new(text: &str) -> WsBuilder { | ||
308 | WsBuilder(SourceFile::parse(text).ok().unwrap()) | ||
309 | } | ||
310 | pub(crate) fn ws(&self) -> SyntaxToken { | ||
311 | self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() | ||
312 | } | ||
313 | } | ||
314 | |||
315 | } | ||
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 897af2b02..3ca3320f7 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -340,5 +340,4 @@ mod tests { | |||
340 | assert_eq!(assists.next().expect("expected assist").0.label, "introduce variable"); | 340 | assert_eq!(assists.next().expect("expected assist").0.label, "introduce variable"); |
341 | assert_eq!(assists.next().expect("expected assist").0.label, "replace with match"); | 341 | assert_eq!(assists.next().expect("expected assist").0.label, "replace with match"); |
342 | } | 342 | } |
343 | |||
344 | } | 343 | } |
diff --git a/crates/ra_ide_api/src/line_index.rs b/crates/ra_ide_api/src/line_index.rs index 71de8a928..5fedad696 100644 --- a/crates/ra_ide_api/src/line_index.rs +++ b/crates/ra_ide_api/src/line_index.rs | |||
@@ -278,5 +278,4 @@ const C: char = \"メ メ\"; | |||
278 | 278 | ||
279 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextUnit::from_usize(15)); | 279 | assert_eq!(col_index.utf16_to_utf8_col(2, 15), TextUnit::from_usize(15)); |
280 | } | 280 | } |
281 | |||
282 | } | 281 | } |
diff --git a/crates/ra_ide_api/src/runnables.rs b/crates/ra_ide_api/src/runnables.rs index 095ca56c4..8cf58fe79 100644 --- a/crates/ra_ide_api/src/runnables.rs +++ b/crates/ra_ide_api/src/runnables.rs | |||
@@ -229,5 +229,4 @@ mod tests { | |||
229 | let runnables = analysis.runnables(pos.file_id).unwrap(); | 229 | let runnables = analysis.runnables(pos.file_id).unwrap(); |
230 | assert!(runnables.is_empty()) | 230 | assert!(runnables.is_empty()) |
231 | } | 231 | } |
232 | |||
233 | } | 232 | } |
diff --git a/crates/ra_lsp_server/src/markdown.rs b/crates/ra_lsp_server/src/markdown.rs index c1eb0236a..3659edf8e 100644 --- a/crates/ra_lsp_server/src/markdown.rs +++ b/crates/ra_lsp_server/src/markdown.rs | |||
@@ -70,5 +70,4 @@ let a = 1; | |||
70 | "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```" | 70 | "```rust\nfn main(){}\n```\nSome comment.\n```rust\nlet a = 1;\n```" |
71 | ); | 71 | ); |
72 | } | 72 | } |
73 | |||
74 | } | 73 | } |
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs index e2355aff9..6e9e212b7 100644 --- a/crates/ra_parser/src/grammar.rs +++ b/crates/ra_parser/src/grammar.rs | |||
@@ -135,7 +135,6 @@ pub(crate) mod fragments { | |||
135 | 135 | ||
136 | m.complete(p, MACRO_STMTS); | 136 | m.complete(p, MACRO_STMTS); |
137 | } | 137 | } |
138 | |||
139 | } | 138 | } |
140 | 139 | ||
141 | pub(crate) fn reparser( | 140 | pub(crate) fn reparser( |
diff --git a/crates/ra_syntax/Cargo.toml b/crates/ra_syntax/Cargo.toml index 724c38e17..9bc85404a 100644 --- a/crates/ra_syntax/Cargo.toml +++ b/crates/ra_syntax/Cargo.toml | |||
@@ -12,6 +12,8 @@ itertools = "0.8.0" | |||
12 | rowan = "0.6.1" | 12 | rowan = "0.6.1" |
13 | rustc_lexer = "0.1.0" | 13 | rustc_lexer = "0.1.0" |
14 | rustc-hash = "1.0.1" | 14 | rustc-hash = "1.0.1" |
15 | arrayvec = "0.4.10" | ||
16 | once_cell = "1.2.0" | ||
15 | 17 | ||
16 | # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here | 18 | # ideally, `serde` should be enabled by `ra_lsp_server`, but we enable it here |
17 | # to reduce number of compilations | 19 | # to reduce number of compilations |
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs index f464d6534..fdffd8cb1 100644 --- a/crates/ra_syntax/src/ast.rs +++ b/crates/ra_syntax/src/ast.rs | |||
@@ -5,6 +5,7 @@ mod traits; | |||
5 | mod tokens; | 5 | mod tokens; |
6 | mod extensions; | 6 | mod extensions; |
7 | mod expr_extensions; | 7 | mod expr_extensions; |
8 | mod edit; | ||
8 | pub mod make; | 9 | pub mod make; |
9 | 10 | ||
10 | use std::marker::PhantomData; | 11 | use std::marker::PhantomData; |
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs new file mode 100644 index 000000000..c65899812 --- /dev/null +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -0,0 +1,52 @@ | |||
1 | //! This module contains functions for editing syntax trees. As the trees are | ||
2 | //! immutable, all function here return a fresh copy of the tree, instead of | ||
3 | //! doing an in-place modification. | ||
4 | |||
5 | use arrayvec::ArrayVec; | ||
6 | use std::ops::RangeInclusive; | ||
7 | |||
8 | use crate::{ | ||
9 | algo, | ||
10 | ast::{self, make, AstNode}, | ||
11 | InsertPosition, SyntaxElement, | ||
12 | }; | ||
13 | |||
14 | impl ast::FnDef { | ||
15 | #[must_use] | ||
16 | pub fn with_body(&self, body: ast::Block) -> ast::FnDef { | ||
17 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | ||
18 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { | ||
19 | old_body.syntax().clone().into() | ||
20 | } else if let Some(semi) = self.semicolon_token() { | ||
21 | to_insert.push(make::tokens::single_space().into()); | ||
22 | semi.into() | ||
23 | } else { | ||
24 | to_insert.push(make::tokens::single_space().into()); | ||
25 | to_insert.push(body.syntax().clone().into()); | ||
26 | return insert_children(self, InsertPosition::Last, to_insert.into_iter()); | ||
27 | }; | ||
28 | to_insert.push(body.syntax().clone().into()); | ||
29 | let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi); | ||
30 | replace_children(self, replace_range, to_insert.into_iter()) | ||
31 | } | ||
32 | } | ||
33 | |||
34 | #[must_use] | ||
35 | fn insert_children<N: AstNode>( | ||
36 | parent: &N, | ||
37 | position: InsertPosition<SyntaxElement>, | ||
38 | mut to_insert: impl Iterator<Item = SyntaxElement>, | ||
39 | ) -> N { | ||
40 | let new_syntax = algo::insert_children(parent.syntax(), position, &mut to_insert); | ||
41 | N::cast(new_syntax).unwrap() | ||
42 | } | ||
43 | |||
44 | #[must_use] | ||
45 | fn replace_children<N: AstNode>( | ||
46 | parent: &N, | ||
47 | to_replace: RangeInclusive<SyntaxElement>, | ||
48 | mut to_insert: impl Iterator<Item = SyntaxElement>, | ||
49 | ) -> N { | ||
50 | let new_syntax = algo::replace_children(parent.syntax(), to_replace, &mut to_insert); | ||
51 | N::cast(new_syntax).unwrap() | ||
52 | } | ||
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index c06c62b3b..287a40bee 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -133,3 +133,51 @@ fn ast_from_text<N: AstNode>(text: &str) -> N { | |||
133 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | 133 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); |
134 | res | 134 | res |
135 | } | 135 | } |
136 | |||
137 | pub mod tokens { | ||
138 | use crate::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T}; | ||
139 | use once_cell::sync::Lazy; | ||
140 | |||
141 | static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;")); | ||
142 | |||
143 | pub fn comma() -> SyntaxToken { | ||
144 | SOURCE_FILE | ||
145 | .tree() | ||
146 | .syntax() | ||
147 | .descendants_with_tokens() | ||
148 | .filter_map(|it| it.into_token()) | ||
149 | .find(|it| it.kind() == T![,]) | ||
150 | .unwrap() | ||
151 | } | ||
152 | |||
153 | pub fn single_space() -> SyntaxToken { | ||
154 | SOURCE_FILE | ||
155 | .tree() | ||
156 | .syntax() | ||
157 | .descendants_with_tokens() | ||
158 | .filter_map(|it| it.into_token()) | ||
159 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ") | ||
160 | .unwrap() | ||
161 | } | ||
162 | |||
163 | pub fn single_newline() -> SyntaxToken { | ||
164 | SOURCE_FILE | ||
165 | .tree() | ||
166 | .syntax() | ||
167 | .descendants_with_tokens() | ||
168 | .filter_map(|it| it.into_token()) | ||
169 | .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n") | ||
170 | .unwrap() | ||
171 | } | ||
172 | |||
173 | pub struct WsBuilder(SourceFile); | ||
174 | |||
175 | impl WsBuilder { | ||
176 | pub fn new(text: &str) -> WsBuilder { | ||
177 | WsBuilder(SourceFile::parse(text).ok().unwrap()) | ||
178 | } | ||
179 | pub fn ws(&self) -> SyntaxToken { | ||
180 | self.0.syntax().first_child_or_token().unwrap().into_token().unwrap() | ||
181 | } | ||
182 | } | ||
183 | } | ||