2 ast::{self, HasName, HasVisibility},
5 CONST, ENUM, FN, MACRO_DEF, MODULE, STATIC, STRUCT, TRAIT, TYPE_ALIAS, USE, VISIBILITY,
10 use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
12 // Assist: change_visibility
14 // Adds or changes existing visibility specifier.
17 // $0fn frobnicate() {}
21 // pub(crate) fn frobnicate() {}
23 pub(crate) fn change_visibility(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24 if let Some(vis) = ctx.find_node_at_offset::<ast::Visibility>() {
25 return change_vis(acc, vis);
30 fn add_vis(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
31 let item_keyword = ctx.token_at_offset().find(|leaf| {
47 let (offset, target) = if let Some(keyword) = item_keyword {
48 let parent = keyword.parent()?;
50 vec![CONST, STATIC, TYPE_ALIAS, FN, MODULE, STRUCT, ENUM, TRAIT, USE, MACRO_DEF];
51 // Parent is not a definition, can't add visibility
52 if !def_kws.iter().any(|&def_kw| def_kw == parent.kind()) {
55 // Already have visibility, do nothing
56 if parent.children().any(|child| child.kind() == VISIBILITY) {
59 (vis_offset(&parent), keyword.text_range())
60 } else if let Some(field_name) = ctx.find_node_at_offset::<ast::Name>() {
61 let field = field_name.syntax().ancestors().find_map(ast::RecordField::cast)?;
62 if field.name()? != field_name {
63 cov_mark::hit!(change_visibility_field_false_positive);
66 if field.visibility().is_some() {
69 (vis_offset(field.syntax()), field_name.syntax().text_range())
70 } else if let Some(field) = ctx.find_node_at_offset::<ast::TupleField>() {
71 if field.visibility().is_some() {
74 (vis_offset(field.syntax()), field.syntax().text_range())
80 AssistId("change_visibility", AssistKind::RefactorRewrite),
81 "Change visibility to pub(crate)",
84 edit.insert(offset, "pub(crate) ");
89 fn change_vis(acc: &mut Assists, vis: ast::Visibility) -> Option<()> {
90 if vis.syntax().text() == "pub" {
91 let target = vis.syntax().text_range();
93 AssistId("change_visibility", AssistKind::RefactorRewrite),
94 "Change Visibility to pub(crate)",
97 edit.replace(vis.syntax().text_range(), "pub(crate)");
101 if vis.syntax().text() == "pub(crate)" {
102 let target = vis.syntax().text_range();
104 AssistId("change_visibility", AssistKind::RefactorRewrite),
105 "Change visibility to pub",
108 edit.replace(vis.syntax().text_range(), "pub");
117 use crate::tests::{check_assist, check_assist_not_applicable, check_assist_target};
122 fn change_visibility_adds_pub_crate_to_items() {
123 check_assist(change_visibility, "$0fn foo() {}", "pub(crate) fn foo() {}");
124 check_assist(change_visibility, "f$0n foo() {}", "pub(crate) fn foo() {}");
125 check_assist(change_visibility, "$0struct Foo {}", "pub(crate) struct Foo {}");
126 check_assist(change_visibility, "$0mod foo {}", "pub(crate) mod foo {}");
127 check_assist(change_visibility, "$0trait Foo {}", "pub(crate) trait Foo {}");
128 check_assist(change_visibility, "m$0od {}", "pub(crate) mod {}");
129 check_assist(change_visibility, "unsafe f$0n foo() {}", "pub(crate) unsafe fn foo() {}");
130 check_assist(change_visibility, "$0macro foo() {}", "pub(crate) macro foo() {}");
131 check_assist(change_visibility, "$0use foo;", "pub(crate) use foo;");
135 fn change_visibility_works_with_struct_fields() {
138 r"struct S { $0field: u32 }",
139 r"struct S { pub(crate) field: u32 }",
141 check_assist(change_visibility, r"struct S ( $0u32 )", r"struct S ( pub(crate) u32 )");
145 fn change_visibility_field_false_positive() {
146 cov_mark::check!(change_visibility_field_false_positive);
147 check_assist_not_applicable(
149 r"struct S { field: [(); { let $0x = ();}] }",
154 fn change_visibility_pub_to_pub_crate() {
155 check_assist(change_visibility, "$0pub fn foo() {}", "pub(crate) fn foo() {}")
159 fn change_visibility_pub_crate_to_pub() {
160 check_assist(change_visibility, "$0pub(crate) fn foo() {}", "pub fn foo() {}")
164 fn change_visibility_const() {
165 check_assist(change_visibility, "$0const FOO = 3u8;", "pub(crate) const FOO = 3u8;");
169 fn change_visibility_static() {
170 check_assist(change_visibility, "$0static FOO = 3u8;", "pub(crate) static FOO = 3u8;");
174 fn change_visibility_type_alias() {
175 check_assist(change_visibility, "$0type T = ();", "pub(crate) type T = ();");
179 fn change_visibility_handles_comment_attrs() {
196 pub(crate) struct Foo;
202 fn not_applicable_for_enum_variants() {
203 check_assist_not_applicable(
205 r"mod foo { pub enum Foo {Foo1} }
206 fn main() { foo::Foo::Foo1$0 } ",
211 fn change_visibility_target() {
212 check_assist_target(change_visibility, "$0fn foo() {}", "fn");
213 check_assist_target(change_visibility, "pub(crate)$0 fn foo() {}", "pub(crate)");
214 check_assist_target(change_visibility, "struct S { $0field: u32 }", "field");