Skip to content

Commit

Permalink
add new assist to change visibility of all struct fields
Browse files Browse the repository at this point in the history
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
  • Loading branch information
bnjjj committed Nov 21, 2020
1 parent cadf0e9 commit f321a2d
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 0 deletions.
166 changes: 166 additions & 0 deletions crates/assists/src/handlers/change_fields_visibility.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
use syntax::{
ast::{self, VisibilityOwner},
AstNode, TextSize,
};
use test_utils::mark;

use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};

// Assist: change_fields_visibility
//
// Adds visibility for each field inside public struct.
//
// ```
// pub struct <|>Foo {
// bar: usize,
// test: String
// }
// ```
// ->
// ```
// pub struct <|>Foo {
// pub bar: usize,
// pub test: String
// }
// ```
pub(crate) fn change_fields_visibility(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
let strukt = ctx.find_node_at_offset::<ast::Struct>()?;
let vis = strukt.visibility()?;
if vis.pub_token().is_none() {
return None;
}

return add_vis_fields(acc, strukt, vis);
}

fn add_vis_fields(
acc: &mut Assists,
strukt: ast::Struct,
strukt_vis: ast::Visibility,
) -> Option<()> {
let fields = strukt.field_list()?;

let offsets: Vec<TextSize> = match fields {
ast::FieldList::RecordFieldList(record_field_list) => record_field_list
.fields()
.into_iter()
.filter_map(|field| match field.visibility() {
Some(_) => None,
None => Some(vis_offset(field.syntax())),
})
.collect(),
ast::FieldList::TupleFieldList(tuple_field_list) => tuple_field_list
.fields()
.into_iter()
.filter_map(|field| match field.visibility() {
Some(_) => None,
None => Some(vis_offset(field.syntax())),
})
.collect(),
};

if offsets.is_empty() {
mark::hit!(change_fields_visibility_all_fields_already_public);
return None;
}

let new_vis = match strukt_vis.crate_token() {
Some(_) => "pub(crate) ",
None => "pub ",
};

acc.add(
AssistId("change_fields_visibility", AssistKind::RefactorRewrite),
"Make all fields public",
strukt.syntax().text_range(),
|edit| {
for offset in offsets {
edit.insert(offset, new_vis);
}
},
)
}

#[cfg(test)]
mod tests {
use crate::tests::{check_assist, check_assist_not_applicable};

use super::*;

#[test]
fn change_fields_visibility_for_pub() {
check_assist(
change_fields_visibility,
r"pub struct S<|> { field: u32 }",
r"pub struct S { pub field: u32 }",
);
}

#[test]
fn change_fields_visibility_for_pub_several_fields() {
check_assist(
change_fields_visibility,
r"pub struct <|>Foo {
field: u32,
bar: usize
}",
r"pub struct Foo {
pub field: u32,
pub bar: usize
}",
);
}

#[test]
fn change_fields_visibility_for_pub_crate() {
check_assist(
change_fields_visibility,
r"pub(crate) struct <|>Foo {
field: u32,
bar: usize
}",
r"pub(crate) struct Foo {
pub(crate) field: u32,
pub(crate) bar: usize
}",
);
}

#[test]
fn change_fields_visibility_for_pub_already_pub_fields() {
check_assist(
change_fields_visibility,
r"pub struct <|>Foo {
pub(crate) field: u32,
bar: usize
}",
r"pub struct Foo {
pub(crate) field: u32,
pub bar: usize
}",
);
}

#[test]
fn change_fields_visibility_for_pub_already_all_pub_fields() {
mark::check!(change_fields_visibility_all_fields_already_public);
check_assist_not_applicable(
change_fields_visibility,
r"pub struct <|>Foo {
pub(crate) field: u32,
pub bar: usize
}",
);
}

#[test]
fn change_fields_visibility_with_private_struct() {
check_assist_not_applicable(
change_fields_visibility,
r"struct <|>Foo {
field: u32,
bar: usize
}",
)
}
}
2 changes: 2 additions & 0 deletions crates/assists/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ mod handlers {
mod add_turbo_fish;
mod apply_demorgan;
mod auto_import;
mod change_fields_visibility;
mod change_visibility;
mod convert_integer_literal;
mod early_return;
Expand Down Expand Up @@ -175,6 +176,7 @@ mod handlers {
apply_demorgan::apply_demorgan,
auto_import::auto_import,
change_visibility::change_visibility,
change_fields_visibility::change_fields_visibility,
convert_integer_literal::convert_integer_literal,
early_return::convert_to_guarded_return,
expand_glob_import::expand_glob_import,
Expand Down
19 changes: 19 additions & 0 deletions crates/assists/src/tests/generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,25 @@ pub mod std { pub mod collections { pub struct HashMap { } } }
)
}

#[test]
fn doctest_change_fields_visibility() {
check_doc_test(
"change_fields_visibility",
r#####"
pub struct <|>Foo {
bar: usize,
test: String
}
"#####,
r#####"
pub struct <|>Foo {
pub bar: usize,
pub test: String
}
"#####,
)
}

#[test]
fn doctest_change_visibility() {
check_doc_test(
Expand Down

0 comments on commit f321a2d

Please sign in to comment.