diff options
-rw-r--r-- | crates/libeditor/src/code_actions.rs | 28 | ||||
-rw-r--r-- | crates/libeditor/tests/test.rs | 7 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/generated.rs | 1 | ||||
-rw-r--r-- | crates/libsyntax2/src/ast/mod.rs | 30 | ||||
-rw-r--r-- | crates/libsyntax2/src/grammar.ron | 5 |
5 files changed, 51 insertions, 20 deletions
diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs index 4987964d2..6df64be12 100644 --- a/crates/libeditor/src/code_actions.rs +++ b/crates/libeditor/src/code_actions.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | use {TextUnit, File, EditBuilder, Edit}; | 1 | use {TextUnit, File, EditBuilder, Edit}; |
2 | use libsyntax2::{ | 2 | use libsyntax2::{ |
3 | ast::{self, AstNode}, | 3 | ast::{self, AstNode, AttrsOwner}, |
4 | SyntaxKind::COMMA, | 4 | SyntaxKind::COMMA, |
5 | SyntaxNodeRef, | 5 | SyntaxNodeRef, |
6 | SyntaxRoot, | 6 | SyntaxRoot, |
@@ -39,18 +39,28 @@ pub fn flip_comma<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() | |||
39 | } | 39 | } |
40 | 40 | ||
41 | pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { | 41 | pub fn add_derive<'a>(file: &'a File, offset: TextUnit) -> Option<impl FnOnce() -> ActionResult + 'a> { |
42 | let syntax = file.syntax(); | 42 | let nominal = find_node::<ast::NominalDef<_>>(file.syntax_ref(), offset)?; |
43 | let syntax = syntax.as_ref(); | ||
44 | let nominal = find_node::<ast::NominalDef<_>>(syntax, offset)?; | ||
45 | Some(move || { | 43 | Some(move || { |
44 | let derive_attr = nominal | ||
45 | .attrs() | ||
46 | .filter_map(|x| x.as_call()) | ||
47 | .filter(|(name, _arg)| name == "derive") | ||
48 | .map(|(_name, arg)| arg) | ||
49 | .next(); | ||
46 | let mut edit = EditBuilder::new(); | 50 | let mut edit = EditBuilder::new(); |
47 | let node_start = nominal.syntax().range().start(); | 51 | let offset = match derive_attr { |
48 | edit.insert(node_start, "#[derive()]\n".to_string()); | 52 | None => { |
53 | let node_start = nominal.syntax().range().start(); | ||
54 | edit.insert(node_start, "#[derive()]\n".to_string()); | ||
55 | node_start + TextUnit::of_str("#[derive(") | ||
56 | } | ||
57 | Some(tt) => { | ||
58 | tt.syntax().range().end() - TextUnit::of_char(')') | ||
59 | } | ||
60 | }; | ||
49 | ActionResult { | 61 | ActionResult { |
50 | edit: edit.finish(), | 62 | edit: edit.finish(), |
51 | cursor_position: CursorPosition::Offset( | 63 | cursor_position: CursorPosition::Offset(offset), |
52 | node_start + TextUnit::of_str("#[derive(") | ||
53 | ), | ||
54 | } | 64 | } |
55 | }) | 65 | }) |
56 | } | 66 | } |
diff --git a/crates/libeditor/tests/test.rs b/crates/libeditor/tests/test.rs index d5df9d0cc..97919d347 100644 --- a/crates/libeditor/tests/test.rs +++ b/crates/libeditor/tests/test.rs | |||
@@ -116,7 +116,12 @@ fn test_add_derive() { | |||
116 | "struct Foo { a: i32, <|>}", | 116 | "struct Foo { a: i32, <|>}", |
117 | "#[derive(<|>)]\nstruct Foo { a: i32, }", | 117 | "#[derive(<|>)]\nstruct Foo { a: i32, }", |
118 | |file, off| add_derive(file, off).map(|f| f()), | 118 | |file, off| add_derive(file, off).map(|f| f()), |
119 | ) | 119 | ); |
120 | check_action( | ||
121 | "#[derive(Clone)]\nstruct Foo { a: i32<|>, }", | ||
122 | "#[derive(Clone<|>)]\nstruct Foo { a: i32, }", | ||
123 | |file, off| add_derive(file, off).map(|f| f()), | ||
124 | ); | ||
120 | } | 125 | } |
121 | 126 | ||
122 | #[test] | 127 | #[test] |
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs index c575e15df..be3f73f7e 100644 --- a/crates/libsyntax2/src/ast/generated.rs +++ b/crates/libsyntax2/src/ast/generated.rs | |||
@@ -339,6 +339,7 @@ impl<R: TreeRoot> AstNode<R> for NominalDef<R> { | |||
339 | } | 339 | } |
340 | } | 340 | } |
341 | 341 | ||
342 | impl<R: TreeRoot> ast::AttrsOwner<R> for NominalDef<R> {} | ||
342 | impl<R: TreeRoot> NominalDef<R> {} | 343 | impl<R: TreeRoot> NominalDef<R> {} |
343 | 344 | ||
344 | // ParenType | 345 | // ParenType |
diff --git a/crates/libsyntax2/src/ast/mod.rs b/crates/libsyntax2/src/ast/mod.rs index fe8f91d15..d53b12ab8 100644 --- a/crates/libsyntax2/src/ast/mod.rs +++ b/crates/libsyntax2/src/ast/mod.rs | |||
@@ -52,19 +52,31 @@ impl<R: TreeRoot> File<R> { | |||
52 | impl<R: TreeRoot> FnDef<R> { | 52 | impl<R: TreeRoot> FnDef<R> { |
53 | pub fn has_atom_attr(&self, atom: &str) -> bool { | 53 | pub fn has_atom_attr(&self, atom: &str) -> bool { |
54 | self.attrs() | 54 | self.attrs() |
55 | .filter_map(|x| x.value()) | 55 | .filter_map(|x| x.as_atom()) |
56 | .filter_map(|x| as_atom(x)) | ||
57 | .any(|x| x == atom) | 56 | .any(|x| x == atom) |
58 | } | 57 | } |
59 | } | 58 | } |
60 | 59 | ||
61 | fn as_atom<R: TreeRoot>(tt: TokenTree<R>) -> Option<SmolStr> { | 60 | impl<R: TreeRoot> Attr<R> { |
62 | let syntax = tt.syntax_ref(); | 61 | pub fn as_atom(&self) -> Option<SmolStr> { |
63 | let (_bra, attr, _ket) = syntax.children().collect_tuple()?; | 62 | let tt = self.value()?; |
64 | if attr.kind() == IDENT { | 63 | let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?; |
65 | Some(attr.leaf_text().unwrap()) | 64 | if attr.kind() == IDENT { |
66 | } else { | 65 | Some(attr.leaf_text().unwrap()) |
67 | None | 66 | } else { |
67 | None | ||
68 | } | ||
69 | } | ||
70 | |||
71 | pub fn as_call(&self) -> Option<(SmolStr, TokenTree<R>)> { | ||
72 | let tt = self.value()?; | ||
73 | let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?; | ||
74 | let args = TokenTree::cast(args)?; | ||
75 | if attr.kind() == IDENT { | ||
76 | Some((attr.leaf_text().unwrap(), args)) | ||
77 | } else { | ||
78 | None | ||
79 | } | ||
68 | } | 80 | } |
69 | } | 81 | } |
70 | 82 | ||
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron index 4e523da9a..abeffb2c3 100644 --- a/crates/libsyntax2/src/grammar.ron +++ b/crates/libsyntax2/src/grammar.ron | |||
@@ -272,6 +272,9 @@ Grammar( | |||
272 | "DynTraitType", | 272 | "DynTraitType", |
273 | ]), | 273 | ]), |
274 | 274 | ||
275 | "NominalDef": ( enum: ["StructDef", "EnumDef"]), | 275 | "NominalDef": ( |
276 | enum: ["StructDef", "EnumDef"], | ||
277 | traits: [ "AttrsOwner" ], | ||
278 | ), | ||
276 | }, | 279 | }, |
277 | ) | 280 | ) |