Skip to content

Commit 11debaf

Browse files
committed
Migrate fix_visibility to mutable ast
1 parent 8c40fa3 commit 11debaf

File tree

1 file changed

+39
-54
lines changed

1 file changed

+39
-54
lines changed

crates/ide-assists/src/handlers/fix_visibility.rs

Lines changed: 39 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use hir::{db::HirDatabase, HasSource, HasVisibility, ModuleDef, PathResolution, ScopeDef};
22
use ide_db::base_db::FileId;
33
use syntax::{
4-
ast::{self, HasVisibility as _},
5-
AstNode, TextRange, TextSize,
4+
ast::{self, edit_in_place::HasVisibilityEdit, make, HasVisibility as _},
5+
AstNode, TextRange,
66
};
77

8-
use crate::{utils::vis_offset, AssistContext, AssistId, AssistKind, Assists};
8+
use crate::{AssistContext, AssistId, AssistKind, Assists};
99

1010
// FIXME: this really should be a fix for diagnostic, rather than an assist.
1111

@@ -58,11 +58,13 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
5858
return None;
5959
};
6060

61-
let (offset, current_visibility, target, target_file, target_name) =
62-
target_data_for_def(ctx.db(), def)?;
61+
let (vis_owner, target, target_file, target_name) = target_data_for_def(ctx.db(), def)?;
6362

64-
let missing_visibility =
65-
if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" };
63+
let missing_visibility = if current_module.krate() == target_module.krate() {
64+
make::visibility_pub_crate()
65+
} else {
66+
make::visibility_pub()
67+
};
6668

6769
let assist_label = match target_name {
6870
None => format!("Change visibility to {missing_visibility}"),
@@ -71,23 +73,14 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
7173
}
7274
};
7375

74-
acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| {
75-
builder.edit_file(target_file);
76-
match ctx.config.snippet_cap {
77-
Some(cap) => match current_visibility {
78-
Some(current_visibility) => builder.replace_snippet(
79-
cap,
80-
current_visibility.syntax().text_range(),
81-
format!("$0{missing_visibility}"),
82-
),
83-
None => builder.insert_snippet(cap, offset, format!("$0{missing_visibility} ")),
84-
},
85-
None => match current_visibility {
86-
Some(current_visibility) => {
87-
builder.replace(current_visibility.syntax().text_range(), missing_visibility)
88-
}
89-
None => builder.insert(offset, format!("{missing_visibility} ")),
90-
},
76+
acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |edit| {
77+
edit.edit_file(target_file);
78+
79+
let vis_owner = edit.make_mut(vis_owner);
80+
vis_owner.set_visibility(missing_visibility.clone_for_update());
81+
82+
if let Some((cap, vis)) = ctx.config.snippet_cap.zip(vis_owner.visibility()) {
83+
edit.add_tabstop_before(cap, vis);
9184
}
9285
})
9386
}
@@ -107,19 +100,22 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
107100
let target_module = parent.module(ctx.db());
108101

109102
let in_file_source = record_field_def.source(ctx.db())?;
110-
let (offset, current_visibility, target) = match in_file_source.value {
103+
let (vis_owner, target): (ast::AnyHasVisibility, TextRange) = match in_file_source.value {
111104
hir::FieldSource::Named(it) => {
112105
let s = it.syntax();
113-
(vis_offset(s), it.visibility(), s.text_range())
106+
(ast::AnyHasVisibility::cast(s.clone()).unwrap(), s.text_range())
114107
}
115108
hir::FieldSource::Pos(it) => {
116109
let s = it.syntax();
117-
(vis_offset(s), it.visibility(), s.text_range())
110+
(ast::AnyHasVisibility::cast(s.clone()).unwrap(), s.text_range())
118111
}
119112
};
120113

121-
let missing_visibility =
122-
if current_module.krate() == target_module.krate() { "pub(crate)" } else { "pub" };
114+
let missing_visibility = if current_module.krate() == target_module.krate() {
115+
make::visibility_pub_crate()
116+
} else {
117+
make::visibility_pub()
118+
};
123119
let target_file = in_file_source.file_id.original_file(ctx.db());
124120

125121
let target_name = record_field_def.name(ctx.db());
@@ -129,35 +125,26 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>
129125
target_name.display(ctx.db())
130126
);
131127

132-
acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |builder| {
133-
builder.edit_file(target_file);
134-
match ctx.config.snippet_cap {
135-
Some(cap) => match current_visibility {
136-
Some(current_visibility) => builder.replace_snippet(
137-
cap,
138-
current_visibility.syntax().text_range(),
139-
format!("$0{missing_visibility}"),
140-
),
141-
None => builder.insert_snippet(cap, offset, format!("$0{missing_visibility} ")),
142-
},
143-
None => match current_visibility {
144-
Some(current_visibility) => {
145-
builder.replace(current_visibility.syntax().text_range(), missing_visibility)
146-
}
147-
None => builder.insert(offset, format!("{missing_visibility} ")),
148-
},
128+
acc.add(AssistId("fix_visibility", AssistKind::QuickFix), assist_label, target, |edit| {
129+
edit.edit_file(target_file);
130+
131+
let vis_owner = edit.make_mut(vis_owner);
132+
vis_owner.set_visibility(missing_visibility.clone_for_update());
133+
134+
if let Some((cap, vis)) = ctx.config.snippet_cap.zip(vis_owner.visibility()) {
135+
edit.add_tabstop_before(cap, vis);
149136
}
150137
})
151138
}
152139

153140
fn target_data_for_def(
154141
db: &dyn HirDatabase,
155142
def: hir::ModuleDef,
156-
) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId, Option<hir::Name>)> {
143+
) -> Option<(ast::AnyHasVisibility, TextRange, FileId, Option<hir::Name>)> {
157144
fn offset_target_and_file_id<S, Ast>(
158145
db: &dyn HirDatabase,
159146
x: S,
160-
) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId)>
147+
) -> Option<(ast::AnyHasVisibility, TextRange, FileId)>
161148
where
162149
S: HasSource<Ast = Ast>,
163150
Ast: AstNode + ast::HasVisibility,
@@ -166,17 +153,15 @@ fn target_data_for_def(
166153
let in_file_syntax = source.syntax();
167154
let file_id = in_file_syntax.file_id;
168155
let syntax = in_file_syntax.value;
169-
let current_visibility = source.value.visibility();
170156
Some((
171-
vis_offset(syntax),
172-
current_visibility,
157+
ast::AnyHasVisibility::cast(syntax.clone()).unwrap(),
173158
syntax.text_range(),
174159
file_id.original_file(db.upcast()),
175160
))
176161
}
177162

178163
let target_name;
179-
let (offset, current_visibility, target, target_file) = match def {
164+
let (offset, target, target_file) = match def {
180165
hir::ModuleDef::Function(f) => {
181166
target_name = Some(f.name(db));
182167
offset_target_and_file_id(db, f)?
@@ -214,15 +199,15 @@ fn target_data_for_def(
214199
let in_file_source = m.declaration_source(db)?;
215200
let file_id = in_file_source.file_id.original_file(db.upcast());
216201
let syntax = in_file_source.value.syntax();
217-
(vis_offset(syntax), in_file_source.value.visibility(), syntax.text_range(), file_id)
202+
(ast::AnyHasVisibility::cast(syntax.clone()).unwrap(), syntax.text_range(), file_id)
218203
}
219204
// FIXME
220205
hir::ModuleDef::Macro(_) => return None,
221206
// Enum variants can't be private, we can't modify builtin types
222207
hir::ModuleDef::Variant(_) | hir::ModuleDef::BuiltinType(_) => return None,
223208
};
224209

225-
Some((offset, current_visibility, target, target_file, target_name))
210+
Some((offset, target, target_file, target_name))
226211
}
227212

228213
#[cfg(test)]

0 commit comments

Comments
 (0)