1
1
use ide_db:: assists:: { AssistId , AssistKind } ;
2
2
use stdx:: to_lower_snake_case;
3
3
use syntax:: {
4
- ast:: { self , edit:: IndentLevel , HasDocComments , HasName } ,
4
+ ast:: { self , edit:: IndentLevel , HasDocComments , HasName , HasVisibility } ,
5
5
AstNode ,
6
6
} ;
7
7
@@ -12,7 +12,7 @@ use crate::assist_context::{AssistContext, Assists};
12
12
// Adds a documentation template above a function definition / declaration.
13
13
//
14
14
// ```
15
- // fn my_$0func(a: i32, b: i32) -> Result<(), std::io::Error> {
15
+ // pub fn my_$0func(a: i32, b: i32) -> Result<(), std::io::Error> {
16
16
// unimplemented!()
17
17
// }
18
18
// ```
@@ -31,7 +31,7 @@ use crate::assist_context::{AssistContext, Assists};
31
31
// /// # Errors
32
32
// ///
33
33
// /// This function will return an error if .
34
- // fn my_func(a: i32, b: i32) -> Result<(), std::io::Error> {
34
+ // pub fn my_func(a: i32, b: i32) -> Result<(), std::io::Error> {
35
35
// unimplemented!()
36
36
// }
37
37
// ```
@@ -40,17 +40,10 @@ pub(crate) fn generate_documentation_template(
40
40
ctx : & AssistContext ,
41
41
) -> Option < ( ) > {
42
42
let name = ctx. find_node_at_offset :: < ast:: Name > ( ) ?;
43
- let ast_func = ast :: Fn :: cast ( name. syntax ( ) . parent ( ) ? ) ?;
44
- if is_in_trait_impl ( & ast_func) {
43
+ let ast_func = name. syntax ( ) . parent ( ) . and_then ( ast :: Fn :: cast ) ?;
44
+ if is_in_trait_impl ( & ast_func) || ! is_public ( & ast_func ) {
45
45
return None ;
46
46
}
47
- // TODO disable at least examples if function not public, as the example will fail to build on
48
- // `cargo test`. What is the exact criteria of `pub`ness? All parent modules must be `pub`, for
49
- // `impl { fn }` both `fn` and `struct`* must be public.
50
- //
51
- // What about `pub(crate)`?
52
- //
53
- // *: Seems complex but maybe ignoring this criteria can be ignored.
54
47
55
48
let parent_syntax = ast_func. syntax ( ) ;
56
49
let text_range = parent_syntax. text_range ( ) ;
@@ -217,6 +210,21 @@ fn gen_ex_start_helper(ast_func: &ast::Fn, krate_name: String) -> Option<(Vec<St
217
210
Some ( ( lines, ex_helper) )
218
211
}
219
212
213
+ /// Check if the function and all its parent modules are exactly `pub`
214
+ fn is_public ( ast_func : & ast:: Fn ) -> bool {
215
+ has_pub ( ast_func)
216
+ && ast_func
217
+ . syntax ( )
218
+ . ancestors ( )
219
+ . filter_map ( ast:: Module :: cast)
220
+ . all ( |module| has_pub ( & module) )
221
+ }
222
+
223
+ /// Check if visibility is exactly `pub` (not `pub(crate)` for instance)
224
+ fn has_pub < T : HasVisibility > ( item : & T ) -> bool {
225
+ item. visibility ( ) . map ( |v| v. path ( ) . is_none ( ) ) . unwrap_or ( false )
226
+ }
227
+
220
228
/// `None` if function without a body; some bool to guess if function can panic
221
229
fn can_panic ( ast_func : & ast:: Fn ) -> Option < bool > {
222
230
let body = ast_func. body ( ) ?. to_string ( ) ;
@@ -445,12 +453,60 @@ impl MyTrait for MyStruct {
445
453
)
446
454
}
447
455
456
+ #[ test]
457
+ fn not_applicable_if_function_is_private ( ) {
458
+ check_assist_not_applicable ( generate_documentation_template, r#"fn priv$0ate() {}"# ) ;
459
+ }
460
+
461
+ #[ test]
462
+ fn not_applicable_if_function_is_pub_crate ( ) {
463
+ check_assist_not_applicable (
464
+ generate_documentation_template,
465
+ r#"pub(crate) fn pri$0vate() {}"# ,
466
+ ) ;
467
+ }
468
+
469
+ #[ test]
470
+ fn not_applicable_if_function_is_in_private_mod ( ) {
471
+ check_assist_not_applicable (
472
+ generate_documentation_template,
473
+ r#"
474
+ mod PrivateModule {
475
+ pub fn pri$0vate() {}
476
+ }"# ,
477
+ ) ;
478
+ }
479
+
480
+ #[ test]
481
+ fn not_applicable_if_function_is_in_pub_crate_mod ( ) {
482
+ check_assist_not_applicable (
483
+ generate_documentation_template,
484
+ r#"
485
+ pub(crate) mod PrivateModule {
486
+ pub fn pr$0ivate() {}
487
+ }"# ,
488
+ ) ;
489
+ }
490
+
491
+ #[ test]
492
+ fn not_applicable_if_function_is_in_non_public_mod_is_recursive ( ) {
493
+ check_assist_not_applicable (
494
+ generate_documentation_template,
495
+ r#"
496
+ mod ParentPrivateModule {
497
+ pub mod PrivateModule {
498
+ pub fn pr$0ivate() {}
499
+ }
500
+ }"# ,
501
+ ) ;
502
+ }
503
+
448
504
#[ test]
449
505
fn supports_noop_function ( ) {
450
506
check_assist (
451
507
generate_documentation_template,
452
508
r#"
453
- fn no$0op() {}
509
+ pub fn no$0op() {}
454
510
"# ,
455
511
r#"
456
512
/// .
@@ -462,7 +518,7 @@ fn no$0op() {}
462
518
///
463
519
/// noop();
464
520
/// ```
465
- fn noop() {}
521
+ pub fn noop() {}
466
522
"# ,
467
523
) ;
468
524
}
@@ -472,7 +528,7 @@ fn noop() {}
472
528
check_assist (
473
529
generate_documentation_template,
474
530
r#"
475
- fn no$0op_with_param(_a: i32) {}
531
+ pub fn no$0op_with_param(_a: i32) {}
476
532
"# ,
477
533
r#"
478
534
/// .
@@ -484,7 +540,7 @@ fn no$0op_with_param(_a: i32) {}
484
540
///
485
541
/// noop_with_param(_a);
486
542
/// ```
487
- fn noop_with_param(_a: i32) {}
543
+ pub fn noop_with_param(_a: i32) {}
488
544
"# ,
489
545
) ;
490
546
}
@@ -494,7 +550,7 @@ fn noop_with_param(_a: i32) {}
494
550
check_assist (
495
551
generate_documentation_template,
496
552
r#"
497
- unsafe fn no$0op_unsafe() {}
553
+ pub unsafe fn no$0op_unsafe() {}
498
554
"# ,
499
555
r#"
500
556
/// .
@@ -510,7 +566,7 @@ unsafe fn no$0op_unsafe() {}
510
566
/// # Safety
511
567
///
512
568
/// .
513
- unsafe fn noop_unsafe() {}
569
+ pub unsafe fn noop_unsafe() {}
514
570
"# ,
515
571
) ;
516
572
}
@@ -520,7 +576,7 @@ unsafe fn noop_unsafe() {}
520
576
check_assist (
521
577
generate_documentation_template,
522
578
r#"
523
- fn panic$0s_if(a: bool) {
579
+ pub fn panic$0s_if(a: bool) {
524
580
if a {
525
581
panic!();
526
582
}
@@ -546,7 +602,7 @@ fn panic$0s_if(a: bool) {
546
602
/// # Panics
547
603
///
548
604
/// Panics if .
549
- fn panics_if(a: bool) {
605
+ pub fn panics_if(a: bool) {
550
606
if a {
551
607
panic!();
552
608
}
@@ -560,7 +616,7 @@ fn panics_if(a: bool) {
560
616
check_assist (
561
617
generate_documentation_template,
562
618
r#"
563
- fn $0panics_if_not(a: bool) {
619
+ pub fn $0panics_if_not(a: bool) {
564
620
assert!(a == true);
565
621
}
566
622
"# ,
@@ -584,7 +640,7 @@ fn $0panics_if_not(a: bool) {
584
640
/// # Panics
585
641
///
586
642
/// Panics if .
587
- fn panics_if_not(a: bool) {
643
+ pub fn panics_if_not(a: bool) {
588
644
assert!(a == true);
589
645
}
590
646
"# ,
@@ -596,7 +652,7 @@ fn panics_if_not(a: bool) {
596
652
check_assist (
597
653
generate_documentation_template,
598
654
r#"
599
- fn $0panics_if_none(a: Option<()>) {
655
+ pub fn $0panics_if_none(a: Option<()>) {
600
656
a.unwrap();
601
657
}
602
658
"# ,
@@ -620,7 +676,7 @@ fn $0panics_if_none(a: Option<()>) {
620
676
/// # Panics
621
677
///
622
678
/// Panics if .
623
- fn panics_if_none(a: Option<()>) {
679
+ pub fn panics_if_none(a: Option<()>) {
624
680
a.unwrap();
625
681
}
626
682
"# ,
@@ -632,7 +688,7 @@ fn panics_if_none(a: Option<()>) {
632
688
check_assist (
633
689
generate_documentation_template,
634
690
r#"
635
- fn $0panics_if_none2(a: Option<()>) {
691
+ pub fn $0panics_if_none2(a: Option<()>) {
636
692
a.expect("Bouh!");
637
693
}
638
694
"# ,
@@ -656,7 +712,7 @@ fn $0panics_if_none2(a: Option<()>) {
656
712
/// # Panics
657
713
///
658
714
/// Panics if .
659
- fn panics_if_none2(a: Option<()>) {
715
+ pub fn panics_if_none2(a: Option<()>) {
660
716
a.expect("Bouh!");
661
717
}
662
718
"# ,
@@ -668,7 +724,7 @@ fn panics_if_none2(a: Option<()>) {
668
724
check_assist (
669
725
generate_documentation_template,
670
726
r#"
671
- fn returns_a_value$0() -> i32 {
727
+ pub fn returns_a_value$0() -> i32 {
672
728
0
673
729
}
674
730
"# ,
@@ -682,7 +738,7 @@ fn returns_a_value$0() -> i32 {
682
738
///
683
739
/// assert_eq!(returns_a_value(), );
684
740
/// ```
685
- fn returns_a_value() -> i32 {
741
+ pub fn returns_a_value() -> i32 {
686
742
0
687
743
}
688
744
"# ,
@@ -694,7 +750,7 @@ fn returns_a_value() -> i32 {
694
750
check_assist (
695
751
generate_documentation_template,
696
752
r#"
697
- fn returns_a_result$0() -> Result<i32, std::io::Error> {
753
+ pub fn returns_a_result$0() -> Result<i32, std::io::Error> {
698
754
Ok(0)
699
755
}
700
756
"# ,
@@ -712,7 +768,7 @@ fn returns_a_result$0() -> Result<i32, std::io::Error> {
712
768
/// # Errors
713
769
///
714
770
/// This function will return an error if .
715
- fn returns_a_result() -> Result<i32, std::io::Error> {
771
+ pub fn returns_a_result() -> Result<i32, std::io::Error> {
716
772
Ok(0)
717
773
}
718
774
"# ,
@@ -724,7 +780,7 @@ fn returns_a_result() -> Result<i32, std::io::Error> {
724
780
check_assist (
725
781
generate_documentation_template,
726
782
r#"
727
- fn modifies_a_value$0(a: &mut i32) {
783
+ pub fn modifies_a_value$0(a: &mut i32) {
728
784
*a = 0;
729
785
}
730
786
"# ,
@@ -740,7 +796,7 @@ fn modifies_a_value$0(a: &mut i32) {
740
796
/// modifies_a_value(&mut a);
741
797
/// assert_eq!(a, );
742
798
/// ```
743
- fn modifies_a_value(a: &mut i32) {
799
+ pub fn modifies_a_value(a: &mut i32) {
744
800
*a = 0;
745
801
}
746
802
"# ,
@@ -752,7 +808,7 @@ fn modifies_a_value(a: &mut i32) {
752
808
check_assist (
753
809
generate_documentation_template,
754
810
r#"
755
- fn sum3$0(a: i32, b: i32, c: i32) -> i32 {
811
+ pub fn sum3$0(a: i32, b: i32, c: i32) -> i32 {
756
812
a + b + c
757
813
}
758
814
"# ,
@@ -767,7 +823,7 @@ fn sum3$0(a: i32, b: i32, c: i32) -> i32 {
767
823
/// let result = sum3(a, b, c);
768
824
/// assert_eq!(result, );
769
825
/// ```
770
- fn sum3(a: i32, b: i32, c: i32) -> i32 {
826
+ pub fn sum3(a: i32, b: i32, c: i32) -> i32 {
771
827
a + b + c
772
828
}
773
829
"# ,
@@ -779,15 +835,15 @@ fn sum3(a: i32, b: i32, c: i32) -> i32 {
779
835
check_assist (
780
836
generate_documentation_template,
781
837
r#"
782
- mod a {
783
- mod b {
784
- fn no$0op() {}
838
+ pub mod a {
839
+ pub mod b {
840
+ pub fn no$0op() {}
785
841
}
786
842
}
787
843
"# ,
788
844
r#"
789
- mod a {
790
- mod b {
845
+ pub mod a {
846
+ pub mod b {
791
847
/// .
792
848
///
793
849
/// # Examples
@@ -797,7 +853,7 @@ mod a {
797
853
///
798
854
/// noop();
799
855
/// ```
800
- fn noop() {}
856
+ pub fn noop() {}
801
857
}
802
858
}
803
859
"# ,
@@ -809,13 +865,13 @@ mod a {
809
865
check_assist (
810
866
generate_documentation_template,
811
867
r#"
812
- struct MyStruct;
868
+ pub struct MyStruct;
813
869
impl MyStruct {
814
- fn no$0op() {}
870
+ pub fn no$0op() {}
815
871
}
816
872
"# ,
817
873
r#"
818
- struct MyStruct;
874
+ pub struct MyStruct;
819
875
impl MyStruct {
820
876
/// .
821
877
///
@@ -826,7 +882,7 @@ impl MyStruct {
826
882
///
827
883
/// MyStruct::noop();
828
884
/// ```
829
- fn noop() {}
885
+ pub fn noop() {}
830
886
}
831
887
"# ,
832
888
) ;
0 commit comments