Skip to content

Commit

Permalink
Support renaming to strings
Browse files Browse the repository at this point in the history
  • Loading branch information
oxalica committed Sep 6, 2022
1 parent 55cda67 commit b469b93
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Super fast incremental analysis! Scans `all-packages.nix` in less than 0.1s and
- [ ] Names introduced by `inherit`.
- [ ] Names used by `inherit`.
- [ ] Conflict detection.
- [ ] Rename to string literals.
- [x] Rename to string literals.
- [ ] Cross-file analysis.
- [ ] Multi-threaded.

Expand Down
42 changes: 36 additions & 6 deletions crates/ide/src/ide/rename.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,18 @@ pub(crate) fn rename(
new_name: &str,
) -> RenameResult<WorkspaceEdit> {
let (_, name) = find_name(db, fpos).ok_or_else(|| "No references found".to_owned())?;
if !is_valid_ident(new_name) {
return Err("Invalid new identifier".into());
}

let is_new_name_ident = is_valid_ident(new_name);
let new_attr = match is_new_name_ident {
true => new_name.into(),
false => escape_name_to_string(new_name),
};

let file_id = fpos.file_id;
let parse = db.parse(file_id);
let source_map = db.source_map(file_id);

let mut edits = Vec::new();
let new_name = SmolStr::from(new_name);

// Rename definitions.
for ptr in source_map.name_nodes(name) {
Expand All @@ -41,13 +43,16 @@ pub(crate) fn rename(
}
edits.push(TextEdit {
delete: node.text_range(),
insert: new_name.clone(),
insert: new_attr.clone(),
});
}

// Rename usages.
let name_refs = db.name_reference(file_id);
let refs = name_refs.name_references(name).unwrap_or_default();
if !is_new_name_ident && !refs.is_empty() {
return Err("Cannot rename to a string literal while it is referenced".into());
}
for &expr in refs {
let ptr = source_map
.expr_node(expr)
Expand All @@ -58,7 +63,7 @@ pub(crate) fn rename(
}
edits.push(TextEdit {
delete: ptr.text_range(),
insert: new_name.clone(),
insert: new_attr.clone(),
});
}

Expand Down Expand Up @@ -139,6 +144,10 @@ fn is_valid_ident(name: &str) -> bool {
&& !KEYWORDS.contains(&bytes)
}

fn escape_name_to_string(name: &str) -> SmolStr {
("\"".to_owned() + &name.replace('\\', "\\\\").replace('"', "\\\"") + "\"").into()
}

#[cfg(test)]
mod tests {
use crate::base::SourceDatabase;
Expand Down Expand Up @@ -343,4 +352,25 @@ mod tests {
expect!["{ a = rec { b = x; }; a.x = b; }"],
);
}

#[test]
fn rename_to_string() {
check("{ $0a = 1; }", "1", expect![[r#"{ "1" = 1; }"#]]);
check(
"{ $0a.a = 1; a.b = 1; }",
"1",
expect![[r#"{ "1".a = 1; "1".b = 1; }"#]],
);
check("let $0a = 1; in 1", "1", expect![[r#"let "1" = 1; in 1"#]]);
check(
"let $0a = 1; in a",
"1",
expect!["Cannot rename to a string literal while it is referenced"],
);
check(
"rec { $0a = a; }",
"1",
expect!["Cannot rename to a string literal while it is referenced"],
);
}
}

0 comments on commit b469b93

Please sign in to comment.