@@ -27,6 +27,27 @@ pub use ide_db::rename::RenameError;
27
27
28
28
type RenameResult < T > = Result < T , RenameError > ;
29
29
30
+ /// This is similar to `collect::<Result<Vec<_>, _>>`, but unlike it, it succeeds if there is *any* `Ok` item.
31
+ fn ok_if_any < T , E > ( iter : impl Iterator < Item = Result < T , E > > ) -> Result < Vec < T > , E > {
32
+ let mut err = None ;
33
+ let oks = iter
34
+ . filter_map ( |item| match item {
35
+ Ok ( it) => Some ( it) ,
36
+ Err ( it) => {
37
+ err = Some ( it) ;
38
+ None
39
+ }
40
+ } )
41
+ . collect :: < Vec < _ > > ( ) ;
42
+ if !oks. is_empty ( ) {
43
+ Ok ( oks)
44
+ } else if let Some ( err) = err {
45
+ Err ( err)
46
+ } else {
47
+ Ok ( Vec :: new ( ) )
48
+ }
49
+ }
50
+
30
51
/// Prepares a rename. The sole job of this function is to return the TextRange of the thing that is
31
52
/// being targeted for a rename.
32
53
pub ( crate ) fn prepare_rename (
@@ -95,58 +116,57 @@ pub(crate) fn rename(
95
116
alias_fallback ( syntax, position, & new_name. display ( db, edition) . to_string ( ) ) ;
96
117
97
118
let ops: RenameResult < Vec < SourceChange > > = match alias_fallback {
98
- Some ( _) => defs
99
- // FIXME: This can use the `ide_db::rename_reference` (or def.rename) method once we can
100
- // properly find "direct" usages/references.
101
- . map ( |( .., def, new_name, _) | {
102
- match kind {
103
- IdentifierKind :: Ident => ( ) ,
104
- IdentifierKind :: Lifetime => {
105
- bail ! ( "Cannot alias reference to a lifetime identifier" )
106
- }
107
- IdentifierKind :: Underscore => bail ! ( "Cannot alias reference to `_`" ) ,
108
- IdentifierKind :: LowercaseSelf => {
109
- bail ! ( "Cannot rename alias reference to `self`" )
110
- }
111
- } ;
112
- let mut usages = def. usages ( & sema) . all ( ) ;
113
-
114
- // FIXME: hack - removes the usage that triggered this rename operation.
115
- match usages. references . get_mut ( & file_id) . and_then ( |refs| {
116
- refs. iter ( )
117
- . position ( |ref_| ref_. range . contains_inclusive ( position. offset ) )
118
- . map ( |idx| refs. remove ( idx) )
119
- } ) {
120
- Some ( _) => ( ) ,
121
- None => never ! ( ) ,
122
- } ;
123
-
124
- let mut source_change = SourceChange :: default ( ) ;
125
- source_change. extend ( usages. references . get_mut ( & file_id) . iter ( ) . map ( |refs| {
126
- (
127
- position. file_id ,
128
- source_edit_from_references ( db, refs, def, & new_name, edition) ,
129
- )
130
- } ) ) ;
131
-
132
- Ok ( source_change)
133
- } )
134
- . collect ( ) ,
135
- None => defs
136
- . map ( |( .., def, new_name, rename_def) | {
137
- if let Definition :: Local ( local) = def {
138
- if let Some ( self_param) = local. as_self_param ( sema. db ) {
139
- cov_mark:: hit!( rename_self_to_param) ;
140
- return rename_self_to_param ( & sema, local, self_param, & new_name, kind) ;
141
- }
142
- if kind == IdentifierKind :: LowercaseSelf {
143
- cov_mark:: hit!( rename_to_self) ;
144
- return rename_to_self ( & sema, local) ;
145
- }
119
+ Some ( _) => ok_if_any (
120
+ defs
121
+ // FIXME: This can use the `ide_db::rename_reference` (or def.rename) method once we can
122
+ // properly find "direct" usages/references.
123
+ . map ( |( .., def, new_name, _) | {
124
+ match kind {
125
+ IdentifierKind :: Ident => ( ) ,
126
+ IdentifierKind :: Lifetime => {
127
+ bail ! ( "Cannot alias reference to a lifetime identifier" )
128
+ }
129
+ IdentifierKind :: Underscore => bail ! ( "Cannot alias reference to `_`" ) ,
130
+ IdentifierKind :: LowercaseSelf => {
131
+ bail ! ( "Cannot rename alias reference to `self`" )
132
+ }
133
+ } ;
134
+ let mut usages = def. usages ( & sema) . all ( ) ;
135
+
136
+ // FIXME: hack - removes the usage that triggered this rename operation.
137
+ match usages. references . get_mut ( & file_id) . and_then ( |refs| {
138
+ refs. iter ( )
139
+ . position ( |ref_| ref_. range . contains_inclusive ( position. offset ) )
140
+ . map ( |idx| refs. remove ( idx) )
141
+ } ) {
142
+ Some ( _) => ( ) ,
143
+ None => never ! ( ) ,
144
+ } ;
145
+
146
+ let mut source_change = SourceChange :: default ( ) ;
147
+ source_change. extend ( usages. references . get_mut ( & file_id) . iter ( ) . map ( |refs| {
148
+ (
149
+ position. file_id ,
150
+ source_edit_from_references ( db, refs, def, & new_name, edition) ,
151
+ )
152
+ } ) ) ;
153
+
154
+ Ok ( source_change)
155
+ } ) ,
156
+ ) ,
157
+ None => ok_if_any ( defs. map ( |( .., def, new_name, rename_def) | {
158
+ if let Definition :: Local ( local) = def {
159
+ if let Some ( self_param) = local. as_self_param ( sema. db ) {
160
+ cov_mark:: hit!( rename_self_to_param) ;
161
+ return rename_self_to_param ( & sema, local, self_param, & new_name, kind) ;
146
162
}
147
- def. rename ( & sema, new_name. as_str ( ) , rename_def)
148
- } )
149
- . collect ( ) ,
163
+ if kind == IdentifierKind :: LowercaseSelf {
164
+ cov_mark:: hit!( rename_to_self) ;
165
+ return rename_to_self ( & sema, local) ;
166
+ }
167
+ }
168
+ def. rename ( & sema, new_name. as_str ( ) , rename_def)
169
+ } ) ) ,
150
170
} ;
151
171
152
172
ops?. into_iter ( )
@@ -320,7 +340,7 @@ fn find_definitions(
320
340
} )
321
341
} ) ;
322
342
323
- let res: RenameResult < Vec < _ > > = symbols. filter_map ( Result :: transpose) . collect ( ) ;
343
+ let res: RenameResult < Vec < _ > > = ok_if_any ( symbols. filter_map ( Result :: transpose) ) ;
324
344
match res {
325
345
Ok ( v) => {
326
346
// remove duplicates, comparing `Definition`s
0 commit comments