aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_editor/src/assists/change_visibility.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_editor/src/assists/change_visibility.rs')
-rw-r--r--crates/ra_editor/src/assists/change_visibility.rs90
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 @@
1use ra_text_edit::TextEditBuilder;
2use 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
9use crate::assists::LocalEdit;
10
11pub 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)]
47mod 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}