From b0705337bec836604bdb97689d0a44940c6bddae Mon Sep 17 00:00:00 2001 From: Pascal Kuthe Date: Fri, 12 May 2023 16:49:39 +0200 Subject: [PATCH] automatically disable TS when parsing takes longer than 500ms --- helix-core/src/syntax.rs | 23 +++++++++++++++-------- helix-core/tests/indent.rs | 2 +- helix-term/src/ui/markdown.rs | 2 +- helix-term/src/ui/picker.rs | 3 --- helix-view/src/document.rs | 11 ++++++----- 5 files changed, 23 insertions(+), 18 deletions(-) diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs index 005e985de..f36c985e3 100644 --- a/helix-core/src/syntax.rs +++ b/helix-core/src/syntax.rs @@ -768,7 +768,11 @@ fn byte_range_to_str(range: std::ops::Range, source: RopeSlice) -> Cow, loader: Arc) -> Self { + pub fn new( + source: &Rope, + config: Arc, + loader: Arc, + ) -> Option { let root_layer = LanguageLayer { tree: None, config, @@ -793,11 +797,13 @@ impl Syntax { loader, }; - syntax - .update(source, source, &ChangeSet::new(source)) - .unwrap(); + let res = syntax.update(source, source, &ChangeSet::new(source)); - syntax + if res.is_err() { + log::error!("TS parser failed, disabeling TS for the current buffer: {res:?}"); + return None; + } + Some(syntax) } pub fn update( @@ -925,6 +931,7 @@ impl Syntax { PARSER.with(|ts_parser| { let ts_parser = &mut ts_parser.borrow_mut(); + ts_parser.parser.set_timeout_micros(1000 * 500); // half a second is pretty generours let mut cursor = ts_parser.cursors.pop().unwrap_or_else(QueryCursor::new); // TODO: might need to set cursor range cursor.set_byte_range(0..usize::MAX); @@ -2371,7 +2378,7 @@ mod test { let mut cursor = QueryCursor::new(); let config = HighlightConfiguration::new(language, "", "", "").unwrap(); - let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)); + let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)).unwrap(); let root = syntax.tree().root_node(); let mut test = |capture, range| { @@ -2442,7 +2449,7 @@ mod test { fn main() {} ", ); - let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)); + let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)).unwrap(); let tree = syntax.tree(); let root = tree.root_node(); assert_eq!(root.kind(), "source_file"); @@ -2529,7 +2536,7 @@ mod test { let language = get_language(language_name).unwrap(); let config = HighlightConfiguration::new(language, "", "", "").unwrap(); - let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)); + let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)).unwrap(); let root = syntax .tree() diff --git a/helix-core/tests/indent.rs b/helix-core/tests/indent.rs index f558f86f3..409706bb9 100644 --- a/helix-core/tests/indent.rs +++ b/helix-core/tests/indent.rs @@ -72,7 +72,7 @@ fn test_treesitter_indent(file_name: &str, lang_scope: &str) { let language_config = loader.language_config_for_scope(lang_scope).unwrap(); let highlight_config = language_config.highlight_config(&[]).unwrap(); - let syntax = Syntax::new(&doc, highlight_config, std::sync::Arc::new(loader)); + let syntax = Syntax::new(&doc, highlight_config, std::sync::Arc::new(loader)).unwrap(); let indent_query = language_config.indent_query().unwrap(); let text = doc.slice(..); diff --git a/helix-term/src/ui/markdown.rs b/helix-term/src/ui/markdown.rs index fea3de78f..def64434a 100644 --- a/helix-term/src/ui/markdown.rs +++ b/helix-term/src/ui/markdown.rs @@ -51,7 +51,7 @@ pub fn highlighted_code_block<'a>( language.into(), )) .and_then(|config| config.highlight_config(theme.scopes())) - .map(|config| Syntax::new(&rope, config, Arc::clone(&config_loader))); + .and_then(|config| Syntax::new(&rope, config, Arc::clone(&config_loader))); let syntax = match syntax { Some(s) => s, diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 6120bfd1f..d161f786c 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -240,12 +240,10 @@ impl FilePicker { log::info!("highlighting picker item failed"); return }; - log::info!("hmm1"); let Some(Overlay { content: picker, .. }) = compositor.find::>() else { log::info!("picker closed before syntax highlighting finished"); return }; - log::info!("hmm2"); // Try to find a document in the cache let doc = match current_file { PathOrId::Id(doc_id) => doc_mut!(editor, &doc_id), @@ -254,7 +252,6 @@ impl FilePicker { _ => return, }, }; - log::info!("yay"); doc.syntax = Some(syntax); }; Callback::EditorCompositor(Box::new(callback)) diff --git a/helix-view/src/document.rs b/helix-view/src/document.rs index 770341dcd..eb3765679 100644 --- a/helix-view/src/document.rs +++ b/helix-view/src/document.rs @@ -972,8 +972,7 @@ impl Document { ) { if let (Some(language_config), Some(loader)) = (language_config, loader) { if let Some(highlight_config) = language_config.highlight_config(&loader.scopes()) { - let syntax = Syntax::new(&self.text, highlight_config, loader); - self.syntax = Some(syntax); + self.syntax = Syntax::new(&self.text, highlight_config, loader); } self.language = Some(language_config); @@ -1113,9 +1112,11 @@ impl Document { // update tree-sitter syntax tree if let Some(syntax) = &mut self.syntax { // TODO: no unwrap - syntax - .update(&old_doc, &self.text, transaction.changes()) - .unwrap(); + let res = syntax.update(&old_doc, &self.text, transaction.changes()); + if res.is_err() { + log::error!("TS parser failed, disabeling TS for the current buffer: {res:?}"); + self.syntax = None; + } } let changes = transaction.changes();