diff options
Diffstat (limited to 'crates/ra_editor/src/assists/change_visibility.rs')
-rw-r--r-- | crates/ra_editor/src/assists/change_visibility.rs | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/crates/ra_editor/src/assists/change_visibility.rs b/crates/ra_editor/src/assists/change_visibility.rs new file mode 100644 index 000000000..98c218f32 --- /dev/null +++ b/crates/ra_editor/src/assists/change_visibility.rs | |||
@@ -0,0 +1,90 @@ | |||
1 | use ra_text_edit::TextEditBuilder; | ||
2 | use ra_syntax::{ | ||
3 | SourceFileNode, | ||
4 | algo::find_leaf_at_offset, | ||
5 | SyntaxKind::{VISIBILITY, FN_KW, MOD_KW, STRUCT_KW, ENUM_KW, TRAIT_KW, FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF}, | ||
6 | TextUnit, | ||
7 | }; | ||
8 | |||
9 | use crate::assists::LocalEdit; | ||
10 | |||
11 | pub fn change_visibility<'a>( | ||
12 | file: &'a SourceFileNode, | ||
13 | offset: TextUnit, | ||
14 | ) -> Option<impl FnOnce() -> LocalEdit + 'a> { | ||
15 | let syntax = file.syntax(); | ||
16 | |||
17 | let keyword = find_leaf_at_offset(syntax, offset).find(|leaf| match leaf.kind() { | ||
18 | FN_KW | MOD_KW | STRUCT_KW | ENUM_KW | TRAIT_KW => true, | ||
19 | _ => false, | ||
20 | })?; | ||
21 | let parent = keyword.parent()?; | ||
22 | let def_kws = vec![FN_DEF, MODULE, STRUCT_DEF, ENUM_DEF, TRAIT_DEF]; | ||
23 | let node_start = parent.range().start(); | ||
24 | Some(move || { | ||
25 | let mut edit = TextEditBuilder::new(); | ||
26 | |||
27 | if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) | ||
28 | || parent.children().any(|child| child.kind() == VISIBILITY) | ||
29 | { | ||
30 | return LocalEdit { | ||
31 | label: "make pub crate".to_string(), | ||
32 | edit: edit.finish(), | ||
33 | cursor_position: Some(offset), | ||
34 | }; | ||
35 | } | ||
36 | |||
37 | edit.insert(node_start, "pub(crate) ".to_string()); | ||
38 | LocalEdit { | ||
39 | label: "make pub crate".to_string(), | ||
40 | edit: edit.finish(), | ||
41 | cursor_position: Some(node_start), | ||
42 | } | ||
43 | }) | ||
44 | } | ||
45 | |||
46 | #[cfg(test)] | ||
47 | mod tests { | ||
48 | use super::*; | ||
49 | use crate::test_utils::check_action; | ||
50 | |||
51 | #[test] | ||
52 | fn test_change_visibility() { | ||
53 | check_action( | ||
54 | "<|>fn foo() {}", | ||
55 | "<|>pub(crate) fn foo() {}", | ||
56 | |file, off| change_visibility(file, off).map(|f| f()), | ||
57 | ); | ||
58 | check_action( | ||
59 | "f<|>n foo() {}", | ||
60 | "<|>pub(crate) fn foo() {}", | ||
61 | |file, off| change_visibility(file, off).map(|f| f()), | ||
62 | ); | ||
63 | check_action( | ||
64 | "<|>struct Foo {}", | ||
65 | "<|>pub(crate) struct Foo {}", | ||
66 | |file, off| change_visibility(file, off).map(|f| f()), | ||
67 | ); | ||
68 | check_action("<|>mod foo {}", "<|>pub(crate) mod foo {}", |file, off| { | ||
69 | change_visibility(file, off).map(|f| f()) | ||
70 | }); | ||
71 | check_action( | ||
72 | "<|>trait Foo {}", | ||
73 | "<|>pub(crate) trait Foo {}", | ||
74 | |file, off| change_visibility(file, off).map(|f| f()), | ||
75 | ); | ||
76 | check_action("m<|>od {}", "<|>pub(crate) mod {}", |file, off| { | ||
77 | change_visibility(file, off).map(|f| f()) | ||
78 | }); | ||
79 | check_action( | ||
80 | "pub(crate) f<|>n foo() {}", | ||
81 | "pub(crate) f<|>n foo() {}", | ||
82 | |file, off| change_visibility(file, off).map(|f| f()), | ||
83 | ); | ||
84 | check_action( | ||
85 | "unsafe f<|>n foo() {}", | ||
86 | "<|>pub(crate) unsafe fn foo() {}", | ||
87 | |file, off| change_visibility(file, off).map(|f| f()), | ||
88 | ); | ||
89 | } | ||
90 | } | ||