aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_editor/src/code_actions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_editor/src/code_actions.rs')
-rw-r--r--crates/ra_editor/src/code_actions.rs74
1 files changed, 73 insertions, 1 deletions
diff --git a/crates/ra_editor/src/code_actions.rs b/crates/ra_editor/src/code_actions.rs
index 688a89c3d..1d78cb7e8 100644
--- a/crates/ra_editor/src/code_actions.rs
+++ b/crates/ra_editor/src/code_actions.rs
@@ -4,7 +4,7 @@ use ra_syntax::{
4 algo::{find_covering_node, find_leaf_at_offset}, 4 algo::{find_covering_node, find_leaf_at_offset},
5 ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner}, 5 ast::{self, AstNode, AttrsOwner, NameOwner, TypeParamsOwner},
6 Direction, SourceFileNode, 6 Direction, SourceFileNode,
7 SyntaxKind::{COMMA, WHITESPACE, COMMENT}, 7 SyntaxKind::{COMMA, WHITESPACE, COMMENT, VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF},
8 SyntaxNodeRef, TextRange, TextUnit, 8 SyntaxNodeRef, TextRange, TextUnit,
9}; 9};
10 10
@@ -174,6 +174,39 @@ pub fn introduce_variable<'a>(
174 } 174 }
175} 175}
176 176
177pub fn make_pub_crate<'a>(
178 file: &'a SourceFileNode,
179 offset: TextUnit,
180) -> Option<impl FnOnce() -> LocalEdit + 'a> {
181 let syntax = file.syntax();
182
183 let keyword = find_leaf_at_offset(syntax, offset).find(|leaf| match leaf.kind() {
184 FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true,
185 _ => false,
186 })?;
187 let parent = keyword.parent()?;
188 let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF];
189 let node_start = parent.range().start();
190 Some(move || {
191 let mut edit = TextEditBuilder::new();
192
193 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind())
194 || parent.children().any(|child| child.kind() == VISIBILITY)
195 {
196 return LocalEdit {
197 edit: edit.finish(),
198 cursor_position: Some(offset),
199 };
200 }
201
202 edit.insert(node_start, "pub(crate) ".to_string());
203 LocalEdit {
204 edit: edit.finish(),
205 cursor_position: Some(node_start),
206 }
207 })
208}
209
177fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> { 210fn non_trivia_sibling(node: SyntaxNodeRef, direction: Direction) -> Option<SyntaxNodeRef> {
178 node.siblings(direction) 211 node.siblings(direction)
179 .skip(1) 212 .skip(1)
@@ -333,4 +366,43 @@ fn foo() {
333 ); 366 );
334 } 367 }
335 368
369 #[test]
370 fn test_make_pub_crate() {
371 check_action(
372 "<|>fn foo() {}",
373 "<|>pub(crate) fn foo() {}",
374 |file, off| make_pub_crate(file, off).map(|f| f()),
375 );
376 check_action(
377 "f<|>n foo() {}",
378 "<|>pub(crate) fn foo() {}",
379 |file, off| make_pub_crate(file, off).map(|f| f()),
380 );
381 check_action(
382 "<|>struct Foo {}",
383 "<|>pub(crate) struct Foo {}",
384 |file, off| make_pub_crate(file, off).map(|f| f()),
385 );
386 check_action("<|>mod foo {}", "<|>pub(crate) mod foo {}", |file, off| {
387 make_pub_crate(file, off).map(|f| f())
388 });
389 check_action(
390 "<|>trait Foo {}",
391 "<|>pub(crate) trait Foo {}",
392 |file, off| make_pub_crate(file, off).map(|f| f()),
393 );
394 check_action("m<|>od {}", "<|>pub(crate) mod {}", |file, off| {
395 make_pub_crate(file, off).map(|f| f())
396 });
397 check_action(
398 "pub(crate) f<|>n foo() {}",
399 "pub(crate) f<|>n foo() {}",
400 |file, off| make_pub_crate(file, off).map(|f| f()),
401 );
402 check_action(
403 "unsafe f<|>n foo() {}",
404 "<|>pub(crate) unsafe fn foo() {}",
405 |file, off| make_pub_crate(file, off).map(|f| f()),
406 );
407 }
336} 408}