Skip to content

Commit

Permalink
lsp: Rename properties
Browse files Browse the repository at this point in the history
  • Loading branch information
hunger committed Jan 17, 2025
1 parent 00580a7 commit de0fcc4
Show file tree
Hide file tree
Showing 2 changed files with 175 additions and 1 deletion.
172 changes: 172 additions & 0 deletions tools/lsp/common/rename_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@ fn rename_local_symbols(
SyntaxKind::InternalName,
SyntaxKind::ExportIdentifier,
SyntaxKind::ExportName,
SyntaxKind::PropertyDeclaration,
]
.contains(&current.parent().kind())
&& query.is_same_symbol(document_cache, current.clone())
Expand Down Expand Up @@ -565,6 +566,25 @@ impl DeclarationNodeQuery {
common::token_info::TokenInfo::ElementRc(s),
common::token_info::TokenInfo::ElementRc(o),
) => Rc::ptr_eq(s, o),
(
common::token_info::TokenInfo::LocalProperty(s),
common::token_info::TokenInfo::LocalProperty(o),
) => Rc::ptr_eq(&s.source_file, &o.source_file) && s.text_range() == o.text_range(),
(
common::token_info::TokenInfo::NamedReference(nl),
common::token_info::TokenInfo::NamedReference(nr),
) => Rc::ptr_eq(&nl.element(), &nr.element()) && nl.name() == nr.name(),
(
common::token_info::TokenInfo::NamedReference(nr),
common::token_info::TokenInfo::LocalProperty(s),
)
| (
common::token_info::TokenInfo::LocalProperty(s),
common::token_info::TokenInfo::NamedReference(nr),
) => nr.element().borrow().debug.iter().any(|di| {
di.node.source_file.path() == s.source_file.path()
&& di.node.PropertyDeclaration().any(|pd| pd.text_range() == s.text_range())
}),
(_, _) => false,
}
}
Expand Down Expand Up @@ -2657,4 +2677,156 @@ export { XxxYyyZzz as Foo }
}
}
}

#[test]
fn test_rename_property_from_definition() {
let document_cache = test::compile_test_with_sources(
"fluent",
HashMap::from([(
Url::from_file_path(test::main_test_file_name()).unwrap(),
r#"
component re_name-me {
property <bool> re_name-me /* <- TEST_ME_1 */: true;
function re_name-me_(re-name_me: int) { /* 1 */ self.re-name_me = re-name_me >= 42; }
}
export component Bar {
property <bool> re_name-me /* <- TEST_ME_2 */: true;
function re_name-me_(re-name_me: int) { /* 2 */ self.re-name_me = re-name_me >= 42; }
re_name-me { }
}
"#
.to_string(),
)]),
true, // Component `Foo` is replacing a component with the same name
);

let edited_text = rename_tester(&document_cache, &test::main_test_file_name(), "_1");
assert_eq!(edited_text.len(), 1);

assert_eq!(edited_text.len(), 1);
assert!(edited_text[0].contents.contains("component re_name-me {"));
assert!(edited_text[0].contents.contains("property <bool> XxxYyyZzz /* <- TEST_ME_1 "));
assert!(edited_text[0].contents.contains(" <- TEST_ME_1 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 1 */"));
assert!(edited_text[0].contents.contains("/* 1 */ self.XxxYyyZzz = re-name_me >= 42;"));

assert!(edited_text[0].contents.contains("export component Bar {"));
assert!(edited_text[0].contents.contains("property <bool> re_name-me /* <- TEST_ME_2 "));
assert!(edited_text[0].contents.contains(" <- TEST_ME_2 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 2 */"));
assert!(edited_text[0].contents.contains("/* 2 */ self.re-name_me = re-name_me >= 42;"));
assert!(edited_text[0].contents.contains("re_name-me { }"));

let edited_text = rename_tester(&document_cache, &test::main_test_file_name(), "_2");
assert_eq!(edited_text.len(), 1);

assert_eq!(edited_text.len(), 1);
assert!(edited_text[0].contents.contains("component re_name-me {"));
assert!(edited_text[0].contents.contains("property <bool> re_name-me /* <- TEST_ME_1 "));
assert!(edited_text[0].contents.contains(" <- TEST_ME_1 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 1 */"));
assert!(edited_text[0].contents.contains("/* 1 */ self.re-name_me = re-name_me >= 42;"));

assert!(edited_text[0].contents.contains("export component Bar {"));
assert!(edited_text[0].contents.contains("property <bool> XxxYyyZzz /* <- TEST_ME_2 "));
assert!(edited_text[0].contents.contains(" <- TEST_ME_2 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 2 */"));
assert!(edited_text[0].contents.contains("/* 2 */ self.XxxYyyZzz = re-name_me >= 42;"));
assert!(edited_text[0].contents.contains("re_name-me { }"));
}

#[test]
fn test_rename_property_from_use() {
let document_cache = test::compile_test_with_sources(
"fluent",
HashMap::from([(
Url::from_file_path(test::main_test_file_name()).unwrap(),
r#"
component re_name-me {
property <bool> re_name-me /* 1 */: true;
function re_name-me_(re-name_me: int) { /* 1 */ self.re-name_me /* <- TEST_ME_1 */ = re-name_me >= 42; }
}
export component Bar {
property <bool> re_name-me /* 2 */: true;
function re_name-me_(re-name_me: int) { /* 2 */ self.re-name_me /* <- TEST_ME_2 */ = re-name_me >= 42; }
re_name-me { }
}
"#
.to_string(),
)]),
true, // Component `Foo` is replacing a component with the same name
);

let edited_text = rename_tester(&document_cache, &test::main_test_file_name(), "_1");
assert_eq!(edited_text.len(), 1);

assert_eq!(edited_text.len(), 1);
assert!(edited_text[0].contents.contains("component re_name-me {"));
assert!(edited_text[0].contents.contains("property <bool> XxxYyyZzz /* 1 */"));
assert!(edited_text[0].contents.contains(" 1 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 1 */"));
assert!(edited_text[0]
.contents
.contains("/* 1 */ self.XxxYyyZzz /* <- TEST_ME_1 */ = re-name_me >= 42;"));

assert!(edited_text[0].contents.contains("export component Bar {"));
assert!(edited_text[0].contents.contains("property <bool> re_name-me /* 2 "));
assert!(edited_text[0].contents.contains(" 2 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 2 */"));
assert!(edited_text[0]
.contents
.contains("/* 2 */ self.re-name_me /* <- TEST_ME_2 */ = re-name_me >= 42;"));
assert!(edited_text[0].contents.contains("re_name-me { }"));

let edited_text = rename_tester(&document_cache, &test::main_test_file_name(), "_2");
assert_eq!(edited_text.len(), 1);

assert_eq!(edited_text.len(), 1);
assert!(edited_text[0].contents.contains("component re_name-me {"));
assert!(edited_text[0].contents.contains("property <bool> re_name-me /* 1 "));
assert!(edited_text[0].contents.contains(" 1 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 1 */"));
assert!(edited_text[0]
.contents
.contains("/* 1 */ self.re-name_me /* <- TEST_ME_1 */ = re-name_me >= 42;"));

assert!(edited_text[0].contents.contains("export component Bar {"));
assert!(edited_text[0].contents.contains("property <bool> XxxYyyZzz /* 2 "));
assert!(edited_text[0].contents.contains(" 2 */: true;"));
assert!(edited_text[0]
.contents
.contains("function re_name-me_(re-name_me: int) { /* 2 */"));
assert!(edited_text[0]
.contents
.contains("/* 2 */ self.XxxYyyZzz /* <- TEST_ME_2 */ = re-name_me >= 42;"));
assert!(edited_text[0].contents.contains("re_name-me { }"));
}
}
4 changes: 3 additions & 1 deletion tools/lsp/common/token_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ pub fn token_info(document_cache: &common::DocumentCache, token: SyntaxToken) ->
return None;
}
let parent = node.parent()?;
if parent.kind() == SyntaxKind::PropertyChangedCallback {
if [SyntaxKind::PropertyChangedCallback, SyntaxKind::PropertyDeclaration]
.contains(&parent.kind())
{
let prop_name = i_slint_compiler::parser::normalize_identifier(token.text());
let element = syntax_nodes::Element::new(parent.parent()?)?;
if let Some(p) = element.PropertyDeclaration().find_map(|p| {
Expand Down

0 comments on commit de0fcc4

Please sign in to comment.