1
1
//! FIXME: write short doc here
2
2
3
- use hir:: { Function , HirDisplay , SourceAnalyzer , SourceBinder } ;
3
+ use hir:: { HirDisplay , SourceAnalyzer , SourceBinder } ;
4
4
use once_cell:: unsync:: Lazy ;
5
5
use ra_ide_db:: RootDatabase ;
6
6
use ra_prof:: profile;
@@ -112,58 +112,74 @@ fn get_param_name_hints(
112
112
// we need args len to determine whether to skip or not the &self parameter
113
113
. collect :: < Vec < _ > > ( ) ;
114
114
115
- let ( has_self_param, fn_signature) = get_fn_signature ( db, analyzer, & expr) ?;
116
- let parameters = if has_self_param && fn_signature. parameter_names . len ( ) > args. len ( ) {
117
- fn_signature. parameter_names . into_iter ( ) . skip ( 1 )
118
- } else {
119
- fn_signature. parameter_names . into_iter ( ) . skip ( 0 )
120
- } ;
121
-
122
- let hints =
123
- parameters
124
- . zip ( args)
125
- . filter_map ( |( param, arg) | {
126
- if !param. is_empty ( ) {
127
- Some ( ( arg. syntax ( ) . text_range ( ) , param) )
128
- } else {
129
- None
130
- }
131
- } )
132
- . map ( |( range, param_name) | InlayHint {
133
- range,
134
- kind : InlayKind :: ParameterHint ,
135
- label : param_name. into ( ) ,
136
- } ) ;
115
+ let fn_signature = get_fn_signature ( db, analyzer, & expr) ?;
116
+ let n_params_to_skip =
117
+ if fn_signature. has_self_param && fn_signature. parameter_names . len ( ) > args. len ( ) {
118
+ 1
119
+ } else {
120
+ 0
121
+ } ;
122
+ let parameters = fn_signature. parameter_names . iter ( ) . skip ( n_params_to_skip) ;
123
+
124
+ let hints = parameters
125
+ . zip ( args)
126
+ . filter ( |( param, arg) | {
127
+ should_show_param_hint ( & fn_signature, param, & arg. syntax ( ) . to_string ( ) )
128
+ } )
129
+ . map ( |( param_name, arg) | InlayHint {
130
+ range : arg. syntax ( ) . text_range ( ) ,
131
+ kind : InlayKind :: ParameterHint ,
132
+ label : param_name. into ( ) ,
133
+ } ) ;
137
134
138
135
acc. extend ( hints) ;
139
136
Some ( ( ) )
140
137
}
141
138
139
+ fn should_show_param_hint (
140
+ fn_signature : & FunctionSignature ,
141
+ param_name : & str ,
142
+ argument_string : & str ,
143
+ ) -> bool {
144
+ if param_name. is_empty ( ) || argument_string. ends_with ( param_name) {
145
+ return false ;
146
+ }
147
+
148
+ let parameters_len = if fn_signature. has_self_param {
149
+ fn_signature. parameters . len ( ) - 1
150
+ } else {
151
+ fn_signature. parameters . len ( )
152
+ } ;
153
+ // avoid displaying hints for common functions like map, filter, etc.
154
+ if parameters_len == 1 && ( param_name. len ( ) == 1 || param_name == "predicate" ) {
155
+ return false ;
156
+ }
157
+
158
+ true
159
+ }
160
+
142
161
fn get_fn_signature (
143
162
db : & RootDatabase ,
144
163
analyzer : & SourceAnalyzer ,
145
164
expr : & ast:: Expr ,
146
- ) -> Option < ( bool , FunctionSignature ) > {
165
+ ) -> Option < FunctionSignature > {
147
166
match expr {
148
167
ast:: Expr :: CallExpr ( expr) => {
149
168
// FIXME: Type::as_callable is broken for closures
150
169
let callable_def = analyzer. type_of ( db, & expr. expr ( ) ?) ?. as_callable ( ) ?;
151
170
match callable_def {
152
171
hir:: CallableDef :: FunctionId ( it) => {
153
- let fn_def: Function = it. into ( ) ;
154
- Some ( ( fn_def. has_self_param ( db) , FunctionSignature :: from_hir ( db, fn_def) ) )
172
+ Some ( FunctionSignature :: from_hir ( db, it. into ( ) ) )
155
173
}
156
- hir:: CallableDef :: StructId ( it) => FunctionSignature :: from_struct ( db, it. into ( ) )
157
- . map ( |signature| ( false , signature) ) ,
174
+ hir:: CallableDef :: StructId ( it) => FunctionSignature :: from_struct ( db, it. into ( ) ) ,
158
175
hir:: CallableDef :: EnumVariantId ( it) => {
159
176
FunctionSignature :: from_enum_variant ( db, it. into ( ) )
160
- . map ( |signature| ( false , signature) )
161
177
}
162
178
}
163
179
}
164
180
ast:: Expr :: MethodCallExpr ( expr) => {
165
181
let fn_def = analyzer. resolve_method_call ( & expr) ?;
166
- Some ( ( fn_def . has_self_param ( db ) , FunctionSignature :: from_hir ( db, fn_def) ) )
182
+ Some ( FunctionSignature :: from_hir ( db, fn_def) )
167
183
}
168
184
_ => None ,
169
185
}
@@ -723,12 +739,42 @@ fn main() {
723
739
fn function_call_parameter_hint ( ) {
724
740
let ( analysis, file_id) = single_file (
725
741
r#"
742
+ enum CustomOption<T> {
743
+ None,
744
+ Some(T),
745
+ }
746
+
747
+ struct FileId {}
748
+ struct SmolStr {}
749
+
750
+ impl From<&str> for SmolStr {
751
+ fn from(_: &str) -> Self {
752
+ unimplemented!()
753
+ }
754
+ }
755
+
756
+ struct TextRange {}
757
+ struct SyntaxKind {}
758
+ struct NavigationTarget {}
759
+
726
760
struct Test {}
727
761
728
762
impl Test {
729
763
fn method(&self, mut param: i32) -> i32 {
730
764
param * 2
731
765
}
766
+
767
+ fn from_syntax(
768
+ file_id: FileId,
769
+ name: SmolStr,
770
+ focus_range: CustomOption<TextRange>,
771
+ full_range: TextRange,
772
+ kind: SyntaxKind,
773
+ docs: CustomOption<String>,
774
+ description: CustomOption<String>,
775
+ ) -> NavigationTarget {
776
+ NavigationTarget {}
777
+ }
732
778
}
733
779
734
780
fn test_func(mut foo: i32, bar: i32, msg: &str, _: i32, last: i32) -> i32 {
@@ -741,53 +787,144 @@ fn main() {
741
787
let t: Test = Test {};
742
788
t.method(123);
743
789
Test::method(&t, 3456);
790
+
791
+ Test::from_syntax(
792
+ FileId {},
793
+ "impl".into(),
794
+ CustomOption::None,
795
+ TextRange {},
796
+ SyntaxKind {},
797
+ CustomOption::None,
798
+ CustomOption::None,
799
+ );
744
800
}"# ,
745
801
) ;
746
802
747
803
assert_debug_snapshot ! ( analysis. inlay_hints( file_id, None ) . unwrap( ) , @r###"
748
804
[
749
805
InlayHint {
750
- range: [215; 226 ),
806
+ range: [777; 788 ),
751
807
kind: TypeHint,
752
808
label: "i32",
753
809
},
754
810
InlayHint {
755
- range: [259; 260 ),
811
+ range: [821; 822 ),
756
812
kind: ParameterHint,
757
813
label: "foo",
758
814
},
759
815
InlayHint {
760
- range: [262; 263 ),
816
+ range: [824; 825 ),
761
817
kind: ParameterHint,
762
818
label: "bar",
763
819
},
764
820
InlayHint {
765
- range: [265; 272 ),
821
+ range: [827; 834 ),
766
822
kind: ParameterHint,
767
823
label: "msg",
768
824
},
769
825
InlayHint {
770
- range: [277; 288 ),
826
+ range: [839; 850 ),
771
827
kind: ParameterHint,
772
828
label: "last",
773
829
},
774
830
InlayHint {
775
- range: [331; 334 ),
831
+ range: [893; 896 ),
776
832
kind: ParameterHint,
777
833
label: "param",
778
834
},
779
835
InlayHint {
780
- range: [354; 356 ),
836
+ range: [916; 918 ),
781
837
kind: ParameterHint,
782
838
label: "&self",
783
839
},
784
840
InlayHint {
785
- range: [358; 362 ),
841
+ range: [920; 924 ),
786
842
kind: ParameterHint,
787
843
label: "param",
788
844
},
845
+ InlayHint {
846
+ range: [959; 968),
847
+ kind: ParameterHint,
848
+ label: "file_id",
849
+ },
850
+ InlayHint {
851
+ range: [978; 991),
852
+ kind: ParameterHint,
853
+ label: "name",
854
+ },
855
+ InlayHint {
856
+ range: [1001; 1019),
857
+ kind: ParameterHint,
858
+ label: "focus_range",
859
+ },
860
+ InlayHint {
861
+ range: [1029; 1041),
862
+ kind: ParameterHint,
863
+ label: "full_range",
864
+ },
865
+ InlayHint {
866
+ range: [1051; 1064),
867
+ kind: ParameterHint,
868
+ label: "kind",
869
+ },
870
+ InlayHint {
871
+ range: [1074; 1092),
872
+ kind: ParameterHint,
873
+ label: "docs",
874
+ },
875
+ InlayHint {
876
+ range: [1102; 1120),
877
+ kind: ParameterHint,
878
+ label: "description",
879
+ },
789
880
]
790
881
"###
791
882
) ;
792
883
}
884
+
885
+ #[ test]
886
+ fn omitted_parameters_hints_heuristics ( ) {
887
+ let ( analysis, file_id) = single_file (
888
+ r#"
889
+ fn map(f: i32) {}
890
+ fn filter(predicate: i32) {}
891
+
892
+ struct TestVarContainer {
893
+ test_var: i32,
894
+ }
895
+
896
+ struct Test {}
897
+
898
+ impl Test {
899
+ fn map(self, f: i32) -> Self {
900
+ self
901
+ }
902
+
903
+ fn filter(self, predicate: i32) -> Self {
904
+ self
905
+ }
906
+
907
+ fn no_hints_expected(&self, _: i32, test_var: i32) {}
908
+ }
909
+
910
+ fn main() {
911
+ let container: TestVarContainer = TestVarContainer { test_var: 42 };
912
+ let test: Test = Test {};
913
+
914
+ map(22);
915
+ filter(33);
916
+
917
+ let test_processed: Test = test.map(1).filter(2);
918
+
919
+ let test_var: i32 = 55;
920
+ test_processed.no_hints_expected(22, test_var);
921
+ test_processed.no_hints_expected(33, container.test_var);
922
+ }"# ,
923
+ ) ;
924
+
925
+ assert_debug_snapshot ! ( analysis. inlay_hints( file_id, Some ( 8 ) ) . unwrap( ) , @r###"
926
+ []
927
+ "###
928
+ ) ;
929
+ }
793
930
}
0 commit comments