Fix matching braces in jsx/tsx tags (#32196)
Closes #27998 Also fixed an issue where jumping back from closing to opening tags didn't work in javascript due to missing brackets in our tree-sitter query. Release Notes: - N/A --------- Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>
This commit is contained in:
parent
6a8fdbfd62
commit
f62d76159b
4 changed files with 63 additions and 0 deletions
|
@ -2,6 +2,8 @@
|
|||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("<" @open ">" @close)
|
||||
("<" @open "/>" @close)
|
||||
("</" @open ">" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
("`" @open "`" @close)
|
||||
|
|
|
@ -2279,6 +2279,17 @@ fn matching(map: &DisplaySnapshot, display_point: DisplayPoint) -> DisplayPoint
|
|||
line_end = map.max_point().to_point(map);
|
||||
}
|
||||
|
||||
if let Some((opening_range, closing_range)) = map
|
||||
.buffer_snapshot
|
||||
.innermost_enclosing_bracket_ranges(offset..offset, None)
|
||||
{
|
||||
if opening_range.contains(&offset) {
|
||||
return closing_range.start.to_display_point(map);
|
||||
} else if closing_range.contains(&offset) {
|
||||
return opening_range.start.to_display_point(map);
|
||||
}
|
||||
}
|
||||
|
||||
let line_range = map.prev_line_boundary(point).0..line_end;
|
||||
let visible_line_range =
|
||||
line_range.start..Point::new(line_range.end.row, line_range.end.column.saturating_sub(1));
|
||||
|
@ -3242,6 +3253,29 @@ mod test {
|
|||
</a>"#});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_matching_braces_in_tag(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new_typescript(cx).await;
|
||||
|
||||
// test brackets within tags
|
||||
cx.set_shared_state(indoc! {r"function f() {
|
||||
return (
|
||||
<div rules={ˇ[{ a: 1 }]}>
|
||||
<h1>test</h1>
|
||||
</div>
|
||||
);
|
||||
}"})
|
||||
.await;
|
||||
cx.simulate_shared_keystrokes("%").await;
|
||||
cx.shared_state().await.assert_eq(indoc! {r"function f() {
|
||||
return (
|
||||
<div rules={[{ a: 1 }ˇ]}>
|
||||
<h1>test</h1>
|
||||
</div>
|
||||
);
|
||||
}"});
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_comma_semicolon(cx: &mut gpui::TestAppContext) {
|
||||
let mut cx = NeovimBackedTestContext::new(cx).await;
|
||||
|
|
|
@ -183,6 +183,30 @@ impl NeovimBackedTestContext {
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn new_typescript(cx: &mut gpui::TestAppContext) -> NeovimBackedTestContext {
|
||||
#[cfg(feature = "neovim")]
|
||||
cx.executor().allow_parking();
|
||||
// rust stores the name of the test on the current thread.
|
||||
// We use this to automatically name a file that will store
|
||||
// the neovim connection's requests/responses so that we can
|
||||
// run without neovim on CI.
|
||||
let thread = thread::current();
|
||||
let test_name = thread
|
||||
.name()
|
||||
.expect("thread is not named")
|
||||
.split(':')
|
||||
.next_back()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
Self {
|
||||
cx: VimTestContext::new_typescript(cx).await,
|
||||
neovim: NeovimConnection::new(test_name).await,
|
||||
|
||||
last_set_state: None,
|
||||
recent_keystrokes: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn set_shared_state(&mut self, marked_text: &str) {
|
||||
let mode = if marked_text.contains('»') {
|
||||
Mode::Visual
|
||||
|
|
3
crates/vim/test_data/test_matching_braces_in_tag.json
Normal file
3
crates/vim/test_data/test_matching_braces_in_tag.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
{"Put":{"state":"function f() {\n return (\n <div rules={ˇ[{ a: 1 }]}>\n <h1>test</h1>\n </div>\n );\n}"}}
|
||||
{"Key":"%"}
|
||||
{"Get":{"state":"function f() {\n return (\n <div rules={[{ a: 1 }ˇ]}>\n <h1>test</h1>\n </div>\n );\n}","mode":"Normal"}}
|
Loading…
Add table
Add a link
Reference in a new issue