1- use hir:: { self , ModPath } ;
1+ use hir;
22use ra_syntax:: { algo:: SyntaxRewriter , ast, match_ast, AstNode , SmolStr , SyntaxNode } ;
33
44use crate :: {
@@ -50,13 +50,9 @@ pub(crate) fn replace_qualified_name_with_use(
5050
5151 // Now that we've brought the name into scope, re-qualify all paths that could be
5252 // affected (that is, all paths inside the node we added the `use` to).
53- let hir_path = match hir:: Path :: from_ast ( path. clone ( ) ) {
54- Some ( p) => p,
55- None => return ,
56- } ;
5753 let mut rewriter = SyntaxRewriter :: default ( ) ;
5854 let syntax = container. either ( |l| l. syntax ( ) . clone ( ) , |r| r. syntax ( ) . clone ( ) ) ;
59- shorten_paths ( & mut rewriter, syntax, hir_path . mod_path ( ) ) ;
55+ shorten_paths ( & mut rewriter, syntax, path ) ;
6056 builder. rewrite ( rewriter) ;
6157 } ,
6258 )
@@ -83,7 +79,7 @@ fn collect_hir_path_segments(path: &hir::Path) -> Option<Vec<SmolStr>> {
8379}
8480
8581/// Adds replacements to `re` that shorten `path` in all descendants of `node`.
86- fn shorten_paths ( rewriter : & mut SyntaxRewriter < ' static > , node : SyntaxNode , path : & ModPath ) {
82+ fn shorten_paths ( rewriter : & mut SyntaxRewriter < ' static > , node : SyntaxNode , path : ast :: Path ) {
8783 for child in node. children ( ) {
8884 match_ast ! {
8985 match child {
@@ -94,47 +90,57 @@ fn shorten_paths(rewriter: &mut SyntaxRewriter<'static>, node: SyntaxNode, path:
9490 ast:: Module ( _it) => continue ,
9591
9692 ast:: Path ( p) => {
97- match maybe_replace_path( rewriter, & p , path) {
93+ match maybe_replace_path( rewriter, p . clone ( ) , path. clone ( ) ) {
9894 Some ( ( ) ) => { } ,
99- None => shorten_paths( rewriter, p. syntax( ) . clone( ) , path) ,
95+ None => shorten_paths( rewriter, p. syntax( ) . clone( ) , path. clone ( ) ) ,
10096 }
10197 } ,
102- _ => shorten_paths( rewriter, child, path) ,
98+ _ => shorten_paths( rewriter, child, path. clone ( ) ) ,
10399 }
104100 }
105101 }
106102}
107103
108104fn maybe_replace_path (
109- re : & mut SyntaxRewriter < ' static > ,
110- p : & ast:: Path ,
111- path : & ModPath ,
105+ rewriter : & mut SyntaxRewriter < ' static > ,
106+ path : ast:: Path ,
107+ target : ast :: Path ,
112108) -> Option < ( ) > {
113- let hir_path = hir:: Path :: from_ast ( p. clone ( ) ) ?;
114-
115- if hir_path. mod_path ( ) != path {
109+ if !path_eq ( path. clone ( ) , target. clone ( ) ) {
116110 return None ;
117111 }
118112
119- // Replace path with its last "plain" segment.
120- let mut mod_path = hir_path. mod_path ( ) . clone ( ) ;
121- let last = mod_path. segments . len ( ) - 1 ;
122- mod_path. segments . swap ( 0 , last) ;
123- mod_path. segments . truncate ( 1 ) ;
124- mod_path. kind = hir:: PathKind :: Plain ;
125-
126- let mut new_path = crate :: ast_transform:: path_to_ast ( mod_path) ;
127-
128- let type_args = p. segment ( ) . and_then ( |s| s. type_arg_list ( ) ) ;
129- if let Some ( type_args) = type_args {
130- let last_segment = new_path. segment ( ) . unwrap ( ) ;
131- new_path = new_path. with_segment ( last_segment. with_type_args ( type_args) ) ;
113+ // Shorten `path`, leaving only its last segment.
114+ if let Some ( parent) = path. qualifier ( ) {
115+ rewriter. delete ( parent. syntax ( ) ) ;
116+ }
117+ if let Some ( double_colon) = path. coloncolon_token ( ) {
118+ rewriter. delete ( & double_colon) ;
132119 }
133120
134- re. replace ( p. syntax ( ) , new_path. syntax ( ) ) ;
135121 Some ( ( ) )
136122}
137123
124+ fn path_eq ( lhs : ast:: Path , rhs : ast:: Path ) -> bool {
125+ let mut lhs_curr = lhs;
126+ let mut rhs_curr = rhs;
127+ loop {
128+ match ( lhs_curr. segment ( ) , rhs_curr. segment ( ) ) {
129+ ( Some ( lhs) , Some ( rhs) ) if lhs. syntax ( ) . text ( ) == rhs. syntax ( ) . text ( ) => ( ) ,
130+ _ => return false ,
131+ }
132+
133+ match ( lhs_curr. qualifier ( ) , rhs_curr. qualifier ( ) ) {
134+ ( Some ( lhs) , Some ( rhs) ) => {
135+ lhs_curr = lhs;
136+ rhs_curr = rhs;
137+ }
138+ ( None , None ) => return true ,
139+ _ => return false ,
140+ }
141+ }
142+ }
143+
138144#[ cfg( test) ]
139145mod tests {
140146 use crate :: tests:: { check_assist, check_assist_not_applicable} ;
0 commit comments