1- use hir:: { EditionedFileId , FileRange , HasCrate , HasSource , Semantics } ;
1+ use hir:: { EditionedFileId , FieldSource , FileRange , HasCrate , HasSource , Semantics } ;
22use ide_db:: { RootDatabase , assists:: Assist , source_change:: SourceChange , text_edit:: TextEdit } ;
3- use syntax:: { AstNode , TextRange , TextSize , ast:: HasVisibility } ;
3+ use syntax:: {
4+ AstNode , TextRange ,
5+ ast:: { HasName as _, HasVisibility } ,
6+ } ;
47
58use crate :: { Diagnostic , DiagnosticCode , DiagnosticsContext , fix} ;
69
710// Diagnostic: private-field
811//
912// This diagnostic is triggered if the accessed field is not visible from the current module.
1013pub ( crate ) fn private_field ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: PrivateField ) -> Diagnostic {
11- // FIXME: add quickfix
1214 Diagnostic :: new_with_syntax_node_ptr (
1315 ctx,
1416 DiagnosticCode :: RustcHardError ( "E0616" ) ,
@@ -40,8 +42,8 @@ pub(crate) fn field_is_private_fixes(
4042
4143 let source = private_field. source ( sema. db ) ?;
4244 let existing_visibility = match & source. value {
43- hir :: FieldSource :: Named ( it) => it. visibility ( ) ,
44- hir :: FieldSource :: Pos ( it) => it. visibility ( ) ,
45+ FieldSource :: Named ( it) => it. visibility ( ) ,
46+ FieldSource :: Pos ( it) => it. visibility ( ) ,
4547 } ;
4648 let range = match existing_visibility {
4749 Some ( visibility) => {
@@ -50,11 +52,19 @@ pub(crate) fn field_is_private_fixes(
5052 source. with_value ( visibility. syntax ( ) ) . original_file_range_opt ( sema. db ) ?. 0
5153 }
5254 None => {
53- let ( range, _) = source. syntax ( ) . original_file_range_opt ( sema. db ) ?;
54- FileRange {
55- file_id : range. file_id ,
56- range : TextRange :: at ( range. range . start ( ) , TextSize :: new ( 0 ) ) ,
57- }
55+ let ( range, _) = source
56+ . map ( |it| {
57+ Some ( match it {
58+ FieldSource :: Named ( it) => {
59+ it. unsafe_token ( ) . or ( it. name ( ) ?. ident_token ( ) ) ?. text_range ( )
60+ }
61+ FieldSource :: Pos ( it) => it. ty ( ) ?. syntax ( ) . text_range ( ) ,
62+ } )
63+ } )
64+ . transpose ( ) ?
65+ . original_node_file_range_opt ( sema. db ) ?;
66+
67+ FileRange { file_id : range. file_id , range : TextRange :: empty ( range. range . start ( ) ) }
5868 }
5969 } ;
6070 let source_change = SourceChange :: from_text_edit (
@@ -225,6 +235,136 @@ pub mod foo {
225235
226236fn foo(v: foo::bar::Struct) {
227237 v.field;
238+ }
239+ "# ,
240+ ) ;
241+ }
242+
243+ #[ test]
244+ fn change_visibility_of_field_with_doc_comment ( ) {
245+ check_fix (
246+ r#"
247+ pub mod foo {
248+ pub struct Foo {
249+ /// This is a doc comment
250+ bar: u32,
251+ }
252+ }
253+
254+ fn main() {
255+ let x = foo::Foo { bar: 0 };
256+ x.bar$0;
257+ }
258+ "# ,
259+ r#"
260+ pub mod foo {
261+ pub struct Foo {
262+ /// This is a doc comment
263+ pub(crate) bar: u32,
264+ }
265+ }
266+
267+ fn main() {
268+ let x = foo::Foo { bar: 0 };
269+ x.bar;
270+ }
271+ "# ,
272+ ) ;
273+ }
274+
275+ #[ test]
276+ fn change_visibility_of_field_with_line_comment ( ) {
277+ check_fix (
278+ r#"
279+ pub mod foo {
280+ pub struct Foo {
281+ // This is a line comment
282+ bar: u32,
283+ }
284+ }
285+
286+ fn main() {
287+ let x = foo::Foo { bar: 0 };
288+ x.bar$0;
289+ }
290+ "# ,
291+ r#"
292+ pub mod foo {
293+ pub struct Foo {
294+ // This is a line comment
295+ pub(crate) bar: u32,
296+ }
297+ }
298+
299+ fn main() {
300+ let x = foo::Foo { bar: 0 };
301+ x.bar;
302+ }
303+ "# ,
304+ ) ;
305+ }
306+
307+ #[ test]
308+ fn change_visibility_of_field_with_multiple_doc_comments ( ) {
309+ check_fix (
310+ r#"
311+ pub mod foo {
312+ pub struct Foo {
313+ /// First line
314+ /// Second line
315+ bar: u32,
316+ }
317+ }
318+
319+ fn main() {
320+ let x = foo::Foo { bar: 0 };
321+ x.bar$0;
322+ }
323+ "# ,
324+ r#"
325+ pub mod foo {
326+ pub struct Foo {
327+ /// First line
328+ /// Second line
329+ pub(crate) bar: u32,
330+ }
331+ }
332+
333+ fn main() {
334+ let x = foo::Foo { bar: 0 };
335+ x.bar;
336+ }
337+ "# ,
338+ ) ;
339+ }
340+
341+ #[ test]
342+ fn change_visibility_of_field_with_attr_and_comment ( ) {
343+ check_fix (
344+ r#"
345+ mod foo {
346+ pub struct Foo {
347+ #[rustfmt::skip]
348+ /// First line
349+ /// Second line
350+ bar: u32,
351+ }
352+ }
353+ fn main() {
354+ foo::Foo { $0bar: 42 };
355+ }
356+ "# ,
357+ r#"
358+ mod foo {
359+ pub struct Foo {
360+ #[rustfmt::skip]
361+ /// First line
362+ /// Second line
363+ pub(crate) bar: u32,
364+ }
365+ }
366+ fn main() {
367+ foo::Foo { bar: 42 };
228368}
229369 "# ,
230370 ) ;
0 commit comments