From 7e3cc67e0a11ae1893e0d4cab62b3245e5181d0a Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Tue, 5 Apr 2022 16:00:02 +0200 Subject: [PATCH] Don't reuse old syntax tree when resetting a buffer's language Co-Authored-By: Nathan Sobo --- Cargo.lock | 1 + crates/language/Cargo.toml | 1 + crates/language/src/buffer.rs | 1 + crates/language/src/tests.rs | 47 +++++++++++++++++++++++++++++++---- 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c4a7112abd41bc7ee3621f0f4d8fa88b026e852f..1952e19e58b5c8829120b5b3f5eb041ac69e4d0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2727,6 +2727,7 @@ dependencies = [ "text", "theme", "tree-sitter", + "tree-sitter-json", "tree-sitter-rust", "unindent", "util", diff --git a/crates/language/Cargo.toml b/crates/language/Cargo.toml index 518753fd753418ef144168f7102d72bca8338cd9..0518261f847fa460bbb2d054e7fc65b9019c4686 100644 --- a/crates/language/Cargo.toml +++ b/crates/language/Cargo.toml @@ -57,5 +57,6 @@ util = { path = "../util", features = ["test-support"] } ctor = "0.1" env_logger = "0.8" rand = "0.8.3" +tree-sitter-json = "0.19.0" tree-sitter-rust = "0.20.0" unindent = "0.1.7" diff --git a/crates/language/src/buffer.rs b/crates/language/src/buffer.rs index eb68b8bbddb1af10cd7538398430600d361a2e15..348ea225cdc008df5e6d9b506ca84c0327be8126 100644 --- a/crates/language/src/buffer.rs +++ b/crates/language/src/buffer.rs @@ -486,6 +486,7 @@ impl Buffer { } pub fn set_language(&mut self, language: Option>, cx: &mut ModelContext) { + *self.syntax_tree.lock() = None; self.language = language; self.reparse(cx); } diff --git a/crates/language/src/tests.rs b/crates/language/src/tests.rs index 0acd4d7d2ffc5a5d9e8db4957da1d04c7430b02c..921a2343d470d3aa624e21eb47f577302549125c 100644 --- a/crates/language/src/tests.rs +++ b/crates/language/src/tests.rs @@ -276,12 +276,32 @@ async fn test_reparse(cx: &mut gpui::TestAppContext) { "arguments: (arguments (identifier)))))))", ) ); +} - fn get_tree_sexp(buffer: &ModelHandle, cx: &gpui::TestAppContext) -> String { - buffer.read_with(cx, |buffer, _| { - buffer.syntax_tree().unwrap().root_node().to_sexp() - }) - } +#[gpui::test] +async fn test_resetting_language(cx: &mut gpui::TestAppContext) { + let buffer = cx.add_model(|cx| { + let mut buffer = Buffer::new(0, "{}", cx).with_language(Arc::new(rust_lang()), cx); + buffer.set_sync_parse_timeout(Duration::ZERO); + buffer + }); + + // Wait for the initial text to parse + buffer + .condition(&cx, |buffer, _| !buffer.is_parsing()) + .await; + assert_eq!( + get_tree_sexp(&buffer, &cx), + "(source_file (expression_statement (block)))" + ); + + buffer.update(cx, |buffer, cx| { + buffer.set_language(Some(Arc::new(json_lang())), cx) + }); + buffer + .condition(&cx, |buffer, _| !buffer.is_parsing()) + .await; + assert_eq!(get_tree_sexp(&buffer, &cx), "(document (object))"); } #[gpui::test] @@ -978,6 +998,23 @@ fn rust_lang() -> Language { .unwrap() } +fn json_lang() -> Language { + Language::new( + LanguageConfig { + name: "Json".into(), + path_suffixes: vec!["js".to_string()], + ..Default::default() + }, + Some(tree_sitter_json::language()), + ) +} + +fn get_tree_sexp(buffer: &ModelHandle, cx: &gpui::TestAppContext) -> String { + buffer.read_with(cx, |buffer, _| { + buffer.syntax_tree().unwrap().root_node().to_sexp() + }) +} + fn empty(point: Point) -> Range { point..point }