Skip to content

Commit cf969d2

Browse files
authored
Merge pull request #19869 from MatrixFrog/publicize_field
Add a quickfix for accessing a private field of a struct
2 parents ed2ae94 + 4055436 commit cf969d2

File tree

6 files changed

+138
-182
lines changed

6 files changed

+138
-182
lines changed

crates/hir-ty/src/infer.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ use chalk_ir::{
3535
use either::Either;
3636
use hir_def::{
3737
AdtId, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, GenericParamId,
38-
ImplId, ItemContainerId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId, VariantId,
38+
ImplId, ItemContainerId, LocalFieldId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId,
39+
VariantId,
3940
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
4041
expr_store::{Body, ExpressionStore, HygieneId, path::Path},
4142
hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
@@ -207,7 +208,7 @@ pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>;
207208
pub enum InferenceDiagnostic {
208209
NoSuchField {
209210
field: ExprOrPatId,
210-
private: bool,
211+
private: Option<LocalFieldId>,
211212
variant: VariantId,
212213
},
213214
PrivateField {

crates/hir-ty/src/infer/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,7 +554,7 @@ impl InferenceContext<'_> {
554554
self.push_diagnostic(
555555
InferenceDiagnostic::NoSuchField {
556556
field: field.expr.into(),
557-
private: true,
557+
private: Some(local_id),
558558
variant: def,
559559
},
560560
);
@@ -564,7 +564,7 @@ impl InferenceContext<'_> {
564564
None => {
565565
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
566566
field: field.expr.into(),
567-
private: false,
567+
private: None,
568568
variant: def,
569569
});
570570
None

crates/hir-ty/src/infer/pat.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ impl InferenceContext<'_> {
143143
{
144144
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
145145
field: inner.into(),
146-
private: true,
146+
private: Some(local_id),
147147
variant: def,
148148
});
149149
}
@@ -157,7 +157,7 @@ impl InferenceContext<'_> {
157157
None => {
158158
self.push_diagnostic(InferenceDiagnostic::NoSuchField {
159159
field: inner.into(),
160-
private: false,
160+
private: None,
161161
variant: def,
162162
});
163163
self.err_ty()

crates/hir/src/diagnostics.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ pub struct MalformedDerive {
224224
#[derive(Debug)]
225225
pub struct NoSuchField {
226226
pub field: InFile<AstPtr<Either<ast::RecordExprField, ast::RecordPatField>>>,
227-
pub private: bool,
227+
pub private: Option<Field>,
228228
pub variant: VariantId,
229229
}
230230

@@ -648,6 +648,7 @@ impl AnyDiagnostic {
648648
}
649649
ExprOrPatId::PatId(pat) => source_map.pat_field_syntax(pat),
650650
};
651+
let private = private.map(|id| Field { id, parent: variant.into() });
651652
NoSuchField { field: expr_or_pat, private, variant }.into()
652653
}
653654
&InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {

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

Lines changed: 2 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ use syntax::{
77

88
use crate::{AssistContext, AssistId, Assists};
99

10-
// FIXME: this really should be a fix for diagnostic, rather than an assist.
11-
1210
// Assist: fix_visibility
1311
//
12+
// Note that there is some duplication between this and the no_such_field diagnostic.
13+
//
1414
// Makes inaccessible item public.
1515
//
1616
// ```
@@ -32,7 +32,6 @@ use crate::{AssistContext, AssistId, Assists};
3232
// ```
3333
pub(crate) fn fix_visibility(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
3434
add_vis_to_referenced_module_def(acc, ctx)
35-
.or_else(|| add_vis_to_referenced_record_field(acc, ctx))
3635
}
3736

3837
fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
@@ -88,59 +87,6 @@ fn add_vis_to_referenced_module_def(acc: &mut Assists, ctx: &AssistContext<'_>)
8887
})
8988
}
9089

91-
fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
92-
let record_field: ast::RecordExprField = ctx.find_node_at_offset()?;
93-
let (record_field_def, _, _) = ctx.sema.resolve_record_field(&record_field)?;
94-
95-
let current_module = ctx.sema.scope(record_field.syntax())?.module();
96-
let current_edition = current_module.krate().edition(ctx.db());
97-
let visibility = record_field_def.visibility(ctx.db());
98-
if visibility.is_visible_from(ctx.db(), current_module.into()) {
99-
return None;
100-
}
101-
102-
let parent = record_field_def.parent_def(ctx.db());
103-
let parent_name = parent.name(ctx.db());
104-
let target_module = parent.module(ctx.db());
105-
106-
let in_file_source = record_field_def.source(ctx.db())?;
107-
let (vis_owner, target) = match in_file_source.value {
108-
hir::FieldSource::Named(it) => {
109-
let range = it.syntax().text_range();
110-
(ast::AnyHasVisibility::new(it), range)
111-
}
112-
hir::FieldSource::Pos(it) => {
113-
let range = it.syntax().text_range();
114-
(ast::AnyHasVisibility::new(it), range)
115-
}
116-
};
117-
118-
let missing_visibility = if current_module.krate() == target_module.krate() {
119-
make::visibility_pub_crate()
120-
} else {
121-
make::visibility_pub()
122-
};
123-
let target_file = in_file_source.file_id.original_file(ctx.db());
124-
125-
let target_name = record_field_def.name(ctx.db());
126-
let assist_label = format!(
127-
"Change visibility of {}.{} to {missing_visibility}",
128-
parent_name.display(ctx.db(), current_edition),
129-
target_name.display(ctx.db(), current_edition)
130-
);
131-
132-
acc.add(AssistId::quick_fix("fix_visibility"), assist_label, target, |edit| {
133-
edit.edit_file(target_file.file_id(ctx.db()));
134-
135-
let vis_owner = edit.make_mut(vis_owner);
136-
vis_owner.set_visibility(Some(missing_visibility.clone_for_update()));
137-
138-
if let Some((cap, vis)) = ctx.config.snippet_cap.zip(vis_owner.visibility()) {
139-
edit.add_tabstop_before(cap, vis);
140-
}
141-
})
142-
}
143-
14490
fn target_data_for_def(
14591
db: &dyn HirDatabase,
14692
def: hir::ModuleDef,
@@ -293,44 +239,6 @@ struct Foo;
293239
);
294240
}
295241

296-
#[test]
297-
fn fix_visibility_of_struct_field() {
298-
check_assist(
299-
fix_visibility,
300-
r"mod foo { pub struct Foo { bar: (), } }
301-
fn main() { foo::Foo { $0bar: () }; } ",
302-
r"mod foo { pub struct Foo { $0pub(crate) bar: (), } }
303-
fn main() { foo::Foo { bar: () }; } ",
304-
);
305-
check_assist(
306-
fix_visibility,
307-
r"
308-
//- /lib.rs
309-
mod foo;
310-
fn main() { foo::Foo { $0bar: () }; }
311-
//- /foo.rs
312-
pub struct Foo { bar: () }
313-
",
314-
r"pub struct Foo { $0pub(crate) bar: () }
315-
",
316-
);
317-
check_assist_not_applicable(
318-
fix_visibility,
319-
r"mod foo { pub struct Foo { pub bar: (), } }
320-
fn main() { foo::Foo { $0bar: () }; } ",
321-
);
322-
check_assist_not_applicable(
323-
fix_visibility,
324-
r"
325-
//- /lib.rs
326-
mod foo;
327-
fn main() { foo::Foo { $0bar: () }; }
328-
//- /foo.rs
329-
pub struct Foo { pub bar: () }
330-
",
331-
);
332-
}
333-
334242
#[test]
335243
fn fix_visibility_of_enum_variant_field() {
336244
// Enum variants, as well as their fields, always get the enum's visibility. In fact, rustc
@@ -367,44 +275,6 @@ pub struct Foo { pub bar: () }
367275
);
368276
}
369277

370-
#[test]
371-
fn fix_visibility_of_union_field() {
372-
check_assist(
373-
fix_visibility,
374-
r"mod foo { pub union Foo { bar: (), } }
375-
fn main() { foo::Foo { $0bar: () }; } ",
376-
r"mod foo { pub union Foo { $0pub(crate) bar: (), } }
377-
fn main() { foo::Foo { bar: () }; } ",
378-
);
379-
check_assist(
380-
fix_visibility,
381-
r"
382-
//- /lib.rs
383-
mod foo;
384-
fn main() { foo::Foo { $0bar: () }; }
385-
//- /foo.rs
386-
pub union Foo { bar: () }
387-
",
388-
r"pub union Foo { $0pub(crate) bar: () }
389-
",
390-
);
391-
check_assist_not_applicable(
392-
fix_visibility,
393-
r"mod foo { pub union Foo { pub bar: (), } }
394-
fn main() { foo::Foo { $0bar: () }; } ",
395-
);
396-
check_assist_not_applicable(
397-
fix_visibility,
398-
r"
399-
//- /lib.rs
400-
mod foo;
401-
fn main() { foo::Foo { $0bar: () }; }
402-
//- /foo.rs
403-
pub union Foo { pub bar: () }
404-
",
405-
);
406-
}
407-
408278
#[test]
409279
fn fix_visibility_of_const() {
410280
check_assist(
@@ -570,19 +440,6 @@ foo::Bar$0
570440
pub(crate) struct Bar;
571441
",
572442
r"$0pub struct Bar;
573-
",
574-
);
575-
check_assist(
576-
fix_visibility,
577-
r"
578-
//- /main.rs crate:a deps:foo
579-
fn main() {
580-
foo::Foo { $0bar: () };
581-
}
582-
//- /lib.rs crate:foo
583-
pub struct Foo { pub(crate) bar: () }
584-
",
585-
r"pub struct Foo { $0pub bar: () }
586443
",
587444
);
588445
}

0 commit comments

Comments
 (0)