2
2
3
3
use hir:: ModuleSource ;
4
4
use ra_db:: { RelativePath , RelativePathBuf , SourceDatabase , SourceDatabaseExt } ;
5
- use ra_syntax:: { algo:: find_node_at_offset, ast, AstNode , SyntaxNode } ;
5
+ use ra_syntax:: { algo:: find_node_at_offset, ast, tokenize , AstNode , SyntaxKind , SyntaxNode } ;
6
6
use ra_text_edit:: TextEdit ;
7
7
8
8
use crate :: {
@@ -17,6 +17,13 @@ pub(crate) fn rename(
17
17
position : FilePosition ,
18
18
new_name : & str ,
19
19
) -> Option < RangeInfo < SourceChange > > {
20
+ let tokens = tokenize ( new_name) ;
21
+ if tokens. len ( ) != 1
22
+ || ( tokens[ 0 ] . kind != SyntaxKind :: IDENT && tokens[ 0 ] . kind != SyntaxKind :: UNDERSCORE )
23
+ {
24
+ return None ;
25
+ }
26
+
20
27
let parse = db. parse ( position. file_id ) ;
21
28
if let Some ( ( ast_name, ast_module) ) =
22
29
find_name_and_module_at_offset ( parse. tree ( ) . syntax ( ) , position)
@@ -123,6 +130,49 @@ mod tests {
123
130
mock_analysis:: analysis_and_position, mock_analysis:: single_file_with_position, FileId ,
124
131
} ;
125
132
133
+ #[ test]
134
+ fn test_rename_to_underscore ( ) {
135
+ test_rename (
136
+ r#"
137
+ fn main() {
138
+ let i<|> = 1;
139
+ }"# ,
140
+ "_" ,
141
+ r#"
142
+ fn main() {
143
+ let _ = 1;
144
+ }"# ,
145
+ ) ;
146
+ }
147
+
148
+ #[ test]
149
+ fn test_rename_to_raw_identifier ( ) {
150
+ test_rename (
151
+ r#"
152
+ fn main() {
153
+ let i<|> = 1;
154
+ }"# ,
155
+ "r#fn" ,
156
+ r#"
157
+ fn main() {
158
+ let r#fn = 1;
159
+ }"# ,
160
+ ) ;
161
+ }
162
+
163
+ #[ test]
164
+ fn test_rename_to_invalid_identifier ( ) {
165
+ let ( analysis, position) = single_file_with_position (
166
+ "
167
+ fn main() {
168
+ let i<|> = 1;
169
+ }" ,
170
+ ) ;
171
+ let new_name = "invalid!" ;
172
+ let source_change = analysis. rename ( position, new_name) . unwrap ( ) ;
173
+ assert ! ( source_change. is_none( ) ) ;
174
+ }
175
+
126
176
#[ test]
127
177
fn test_rename_for_local ( ) {
128
178
test_rename (
0 commit comments