@@ -39,6 +39,7 @@ pub struct ImportEdit {
3939 pub position : TextSize ,
4040 pub insert_text : String ,
4141 pub display_text : String ,
42+ pub module_name : String ,
4243}
4344
4445pub enum IntermediateDefinition {
@@ -198,7 +199,7 @@ pub fn insert_import_edit(
198199 handle_to_import_from : Handle ,
199200 export_name : & str ,
200201 import_format : ImportFormat ,
201- ) -> ( TextSize , String , String ) {
202+ ) -> ImportEdit {
202203 let use_absolute_import = match import_format {
203204 ImportFormat :: Absolute => true ,
204205 ImportFormat :: Relative => {
@@ -235,12 +236,7 @@ pub fn insert_import_edit_with_forced_import_format(
235236 handle_to_import_from : Handle ,
236237 export_name : & str ,
237238 use_absolute_import : bool ,
238- ) -> ( TextSize , String , String ) {
239- let position = if let Some ( first_stmt) = ast. body . iter ( ) . find ( |stmt| !is_docstring_stmt ( stmt) ) {
240- first_stmt. range ( ) . start ( )
241- } else {
242- ast. range . end ( )
243- } ;
239+ ) -> ImportEdit {
244240 let module_name_to_import = if use_absolute_import {
245241 handle_to_import_from. module ( )
246242 } else if let Some ( relative_module) = ModuleName :: relative_module_name_between (
@@ -256,14 +252,14 @@ pub fn insert_import_edit_with_forced_import_format(
256252 module_name_to_import. as_str( ) ,
257253 export_name
258254 ) ;
259- if let Some ( ( position , insert_text ) ) =
260- try_extend_existing_from_import ( ast, module_name_to_import . as_str ( ) , export_name )
261- {
262- return ImportEdit {
263- position ,
264- insert_text ,
265- display_text ,
266- } ;
255+ if let Some ( edit ) = try_extend_existing_from_import (
256+ ast,
257+ module_name_to_import . as_str ( ) ,
258+ export_name ,
259+ display_text . clone ( ) ,
260+ module_name_to_import . as_str ( ) ,
261+ ) {
262+ return edit ;
267263 }
268264 let position = if let Some ( first_stmt) = ast. body . iter ( ) . find ( |stmt| !is_docstring_stmt ( stmt) ) {
269265 first_stmt. range ( ) . start ( )
@@ -275,7 +271,12 @@ pub fn insert_import_edit_with_forced_import_format(
275271 module_name_to_import. as_str( ) ,
276272 export_name
277273 ) ;
278- ( position, insert_text, module_name_to_import. to_string ( ) )
274+ ImportEdit {
275+ position,
276+ insert_text,
277+ display_text,
278+ module_name : module_name_to_import. to_string ( ) ,
279+ }
279280}
280281
281282/// Some handles must be imported in absolute style,
@@ -299,3 +300,48 @@ fn handle_require_absolute_import(config_finder: &ConfigFinder, handle: &Handle)
299300 . site_package_path ( )
300301 . any ( |search_path| handle. path ( ) . as_path ( ) . starts_with ( search_path) )
301302}
303+
304+ fn try_extend_existing_from_import (
305+ ast : & ModModule ,
306+ target_module_name : & str ,
307+ export_name : & str ,
308+ display_text : String ,
309+ module_name : & str ,
310+ ) -> Option < ImportEdit > {
311+ for stmt in & ast. body {
312+ if let Stmt :: ImportFrom ( import_from) = stmt {
313+ if import_from_module_name ( import_from) == target_module_name {
314+ if import_from
315+ . names
316+ . iter ( )
317+ . any ( |alias| alias. asname . is_none ( ) && alias. name . as_str ( ) == export_name)
318+ {
319+ // Already imported; don't propose a duplicate edit.
320+ return None ;
321+ }
322+ if let Some ( last_alias) = import_from. names . last ( ) {
323+ let position = last_alias. range . end ( ) ;
324+ let insert_text = format ! ( ", {}" , export_name) ;
325+ return Some ( ImportEdit {
326+ position,
327+ insert_text,
328+ display_text,
329+ module_name : module_name. to_owned ( ) ,
330+ } ) ;
331+ }
332+ }
333+ }
334+ }
335+ None
336+ }
337+
338+ fn import_from_module_name ( import_from : & StmtImportFrom ) -> String {
339+ let mut module_name = String :: new ( ) ;
340+ if import_from. level > 0 {
341+ module_name. push_str ( & "." . repeat ( import_from. level as usize ) ) ;
342+ }
343+ if let Some ( module) = & import_from. module {
344+ module_name. push_str ( module. as_str ( ) ) ;
345+ }
346+ module_name
347+ }
0 commit comments