1
+ use hir:: ModuleDef ;
1
2
use ide_db:: assists:: { AssistId , AssistKind } ;
2
3
use stdx:: to_lower_snake_case;
3
4
use syntax:: {
@@ -51,8 +52,6 @@ pub(crate) fn generate_documentation_template(
51
52
let parent_syntax = ast_func. syntax ( ) ;
52
53
let text_range = parent_syntax. text_range ( ) ;
53
54
let indent_level = IndentLevel :: from_node ( & parent_syntax) ;
54
- let krate_name =
55
- ctx. sema . scope ( & parent_syntax) . module ( ) ?. krate ( ) . display_name ( ctx. db ( ) ) ?. to_string ( ) ;
56
55
57
56
acc. add (
58
57
AssistId ( "generate_documentation_template" , AssistKind :: Generate ) ,
@@ -63,7 +62,7 @@ pub(crate) fn generate_documentation_template(
63
62
// Introduction / short function description before the sections
64
63
doc_lines. push ( introduction_builder ( & ast_func) ) ;
65
64
// Then come the sections
66
- if let Some ( mut lines) = examples_builder ( & ast_func, krate_name ) {
65
+ if let Some ( mut lines) = examples_builder ( & ast_func, ctx ) {
67
66
doc_lines. push ( "" . into ( ) ) ;
68
67
doc_lines. append ( & mut lines) ;
69
68
}
@@ -94,16 +93,16 @@ fn introduction_builder(ast_func: &ast::Fn) -> String {
94
93
}
95
94
96
95
/// Builds an `# Examples` section. An option is returned to be able to manage an error in the AST.
97
- fn examples_builder ( ast_func : & ast:: Fn , krate_name : String ) -> Option < Vec < String > > {
96
+ fn examples_builder ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> Option < Vec < String > > {
98
97
let ( no_panic_ex, panic_ex) = if is_in_trait_def ( ast_func) {
99
98
let message = "// Example template not implemented for trait functions" ;
100
99
( Some ( vec ! [ message. into( ) ] ) , Some ( vec ! [ message. into( ) ] ) )
101
100
} else {
102
101
let panic_ex = match can_panic ( ast_func) {
103
- Some ( true ) => gen_panic_ex_template ( ast_func, krate_name . clone ( ) ) ,
102
+ Some ( true ) => gen_panic_ex_template ( ast_func, ctx ) ,
104
103
_ => None ,
105
104
} ;
106
- let no_panic_ex = gen_ex_template ( ast_func, krate_name ) ;
105
+ let no_panic_ex = gen_ex_template ( ast_func, ctx ) ;
107
106
( no_panic_ex, panic_ex)
108
107
} ;
109
108
@@ -146,8 +145,8 @@ fn safety_builder(ast_func: &ast::Fn) -> Option<Vec<String>> {
146
145
147
146
/// Generate an example template which should not panic
148
147
/// `None` if the function has a `self` parameter but is not in an `impl`.
149
- fn gen_ex_template ( ast_func : & ast:: Fn , krate_name : String ) -> Option < Vec < String > > {
150
- let ( mut lines, ex_helper) = gen_ex_start_helper ( ast_func, krate_name ) ?;
148
+ fn gen_ex_template ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> Option < Vec < String > > {
149
+ let ( mut lines, ex_helper) = gen_ex_start_helper ( ast_func, ctx ) ?;
151
150
// Call the function, check result
152
151
if returns_a_value ( ast_func) {
153
152
if count_parameters ( & ex_helper. param_list ) < 3 {
@@ -171,8 +170,8 @@ fn gen_ex_template(ast_func: &ast::Fn, krate_name: String) -> Option<Vec<String>
171
170
172
171
/// Generate an example template which should panic
173
172
/// `None` if the function has a `self` parameter but is not in an `impl`.
174
- fn gen_panic_ex_template ( ast_func : & ast:: Fn , krate_name : String ) -> Option < Vec < String > > {
175
- let ( mut lines, ex_helper) = gen_ex_start_helper ( ast_func, krate_name ) ?;
173
+ fn gen_panic_ex_template ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> Option < Vec < String > > {
174
+ let ( mut lines, ex_helper) = gen_ex_start_helper ( ast_func, ctx ) ?;
176
175
match returns_a_value ( ast_func) {
177
176
true => lines. push ( format ! ( "let _ = {}; // panics" , ex_helper. function_call) ) ,
178
177
false => lines. push ( format ! ( "{}; // panics" , ex_helper. function_call) ) ,
@@ -190,14 +189,14 @@ struct ExHelper {
190
189
191
190
/// Build the start of the example and transmit the useful intermediary results.
192
191
/// `None` if the function has a `self` parameter but is not in an `impl`.
193
- fn gen_ex_start_helper ( ast_func : & ast:: Fn , krate_name : String ) -> Option < ( Vec < String > , ExHelper ) > {
192
+ fn gen_ex_start_helper ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> Option < ( Vec < String > , ExHelper ) > {
194
193
let mut lines = Vec :: new ( ) ;
195
194
let is_unsafe = ast_func. unsafe_token ( ) . is_some ( ) ;
196
195
let param_list = ast_func. param_list ( ) ?;
197
196
let ref_mut_params = ref_mut_params ( & param_list) ;
198
197
let self_name: Option < String > = self_name ( ast_func) ;
199
198
200
- lines. push ( format ! ( "use {};" , build_path( ast_func, krate_name ) ) ) ;
199
+ lines. push ( format ! ( "use {};" , build_path( ast_func, ctx ) ? ) ) ;
201
200
lines. push ( "" . into ( ) ) ;
202
201
if let Some ( self_definition) = self_definition ( ast_func, self_name. as_deref ( ) ) {
203
202
lines. push ( self_definition) ;
@@ -220,6 +219,12 @@ fn is_public(ast_func: &ast::Fn) -> bool {
220
219
. all ( |module| has_pub ( & module) )
221
220
}
222
221
222
+ /// Get the name of the current crate
223
+ fn crate_name ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> Option < String > {
224
+ let krate = ctx. sema . scope ( & ast_func. syntax ( ) ) . module ( ) ?. krate ( ) ;
225
+ Some ( krate. display_name ( ctx. db ( ) ) ?. to_string ( ) )
226
+ }
227
+
223
228
/// Check if visibility is exactly `pub` (not `pub(crate)` for instance)
224
229
fn has_pub < T : HasVisibility > ( item : & T ) -> bool {
225
230
item. visibility ( ) . map ( |v| v. path ( ) . is_none ( ) ) . unwrap_or ( false )
@@ -377,21 +382,16 @@ fn string_vec_from(string_array: &[&str]) -> Vec<String> {
377
382
}
378
383
379
384
/// Helper function to build the path of the module in the which is the node
380
- fn build_path ( ast_func : & ast:: Fn , krate_name : String ) -> String {
381
- let mut path: Vec < String > = ast_func
382
- . syntax ( )
383
- . ancestors ( )
384
- . filter_map ( |m| ast:: Module :: cast ( m) . and_then ( |m| m. name ( ) ) )
385
- . map ( |m| m. to_string ( ) )
386
- . collect ( ) ;
387
- path. push ( krate_name) ;
388
- path. reverse ( ) ;
389
- path. push (
390
- self_partial_type ( ast_func)
391
- . or_else ( || ast_func. name ( ) . map ( |n| n. to_string ( ) ) )
392
- . unwrap_or_else ( || "*" . into ( ) ) ,
393
- ) ;
394
- intersperse_string ( path. into_iter ( ) , "::" )
385
+ fn build_path ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> Option < String > {
386
+ let crate_name = crate_name ( ast_func, ctx) ?;
387
+ let leaf = self_partial_type ( ast_func)
388
+ . or_else ( || ast_func. name ( ) . map ( |n| n. to_string ( ) ) )
389
+ . unwrap_or_else ( || "*" . into ( ) ) ;
390
+ let func_module_def: ModuleDef = ctx. sema . to_def ( ast_func) ?. module ( ctx. db ( ) ) . into ( ) ;
391
+ match func_module_def. canonical_path ( ctx. db ( ) ) {
392
+ Some ( path) => Some ( format ! ( "{}::{}::{}" , crate_name, path, leaf) ) ,
393
+ None => Some ( format ! ( "{}::{}" , crate_name, leaf) ) ,
394
+ }
395
395
}
396
396
397
397
/// Helper function to get the return type of a function
0 commit comments