on master help sign in
automatically disable TS when parsing takes longer than 500ms
b070533Pascal Kuthe
helix-core/src/syntax.rs+15−8
@@ -768,7 +768,11 @@ fn byte_range_to_str(range: std::ops::Range<usize>, source: RopeSlice) -> Cow<st
768}
768}
769
769
770impl Syntax {
770impl Syntax {
771+ pub fn new(
772+ source: &Rope,
771− pub fn new(source: &Rope, config: Arc<HighlightConfiguration>, loader: Arc<Loader>) -> Self {
773+ config: Arc<HighlightConfiguration>,
774+ loader: Arc<Loader>,
775+ ) -> Option<Self> {
772 let root_layer = LanguageLayer {
776 let root_layer = LanguageLayer {
773 tree: None,
777 tree: None,
774 config,
778 config,
@@ -793,11 +797,13 @@ impl Syntax {
793 loader,
797 loader,
794 };
798 };
795
799
796− syntax
797− .update(source, source, &ChangeSet::new(source))
800+ let res = syntax.update(source, source, &ChangeSet::new(source));
798− .unwrap();
799
801
802+ if res.is_err() {
803+ log::error!("TS parser failed, disabeling TS for the current buffer: {res:?}");
804+ return None;
805+ }
800− syntax
806+ Some(syntax)
801 }
807 }
802
808
803 pub fn update(
809 pub fn update(
@@ -925,6 +931,7 @@ impl Syntax {
925
931
926 PARSER.with(|ts_parser| {
932 PARSER.with(|ts_parser| {
927 let ts_parser = &mut ts_parser.borrow_mut();
933 let ts_parser = &mut ts_parser.borrow_mut();
934+ ts_parser.parser.set_timeout_micros(1000 * 500); // half a second is pretty generours
928 let mut cursor = ts_parser.cursors.pop().unwrap_or_else(QueryCursor::new);
935 let mut cursor = ts_parser.cursors.pop().unwrap_or_else(QueryCursor::new);
929 // TODO: might need to set cursor range
936 // TODO: might need to set cursor range
930 cursor.set_byte_range(0..usize::MAX);
937 cursor.set_byte_range(0..usize::MAX);
@@ -2371,7 +2378,7 @@ mod test {
2371 let mut cursor = QueryCursor::new();
2378 let mut cursor = QueryCursor::new();
2372
2379
2373 let config = HighlightConfiguration::new(language, "", "", "").unwrap();
2380 let config = HighlightConfiguration::new(language, "", "", "").unwrap();
2374− let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader));
2381+ let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)).unwrap();
2375
2382
2376 let root = syntax.tree().root_node();
2383 let root = syntax.tree().root_node();
2377 let mut test = |capture, range| {
2384 let mut test = |capture, range| {
@@ -2442,7 +2449,7 @@ mod test {
2442 fn main() {}
2449 fn main() {}
2443 ",
2450 ",
2444 );
2451 );
2445− let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader));
2452+ let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)).unwrap();
2446 let tree = syntax.tree();
2453 let tree = syntax.tree();
2447 let root = tree.root_node();
2454 let root = tree.root_node();
2448 assert_eq!(root.kind(), "source_file");
2455 assert_eq!(root.kind(), "source_file");
@@ -2529,7 +2536,7 @@ mod test {
2529 let language = get_language(language_name).unwrap();
2536 let language = get_language(language_name).unwrap();
2530
2537
2531 let config = HighlightConfiguration::new(language, "", "", "").unwrap();
2538 let config = HighlightConfiguration::new(language, "", "", "").unwrap();
2532− let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader));
2539+ let syntax = Syntax::new(&source, Arc::new(config), Arc::new(loader)).unwrap();
2533
2540
2534 let root = syntax
2541 let root = syntax
2535 .tree()
2542 .tree()
helix-core/tests/indent.rs+1−1
@@ -72,7 +72,7 @@ fn test_treesitter_indent(file_name: &str, lang_scope: &str) {
72
72
73 let language_config = loader.language_config_for_scope(lang_scope).unwrap();
73 let language_config = loader.language_config_for_scope(lang_scope).unwrap();
74 let highlight_config = language_config.highlight_config(&[]).unwrap();
74 let highlight_config = language_config.highlight_config(&[]).unwrap();
75− let syntax = Syntax::new(&doc, highlight_config, std::sync::Arc::new(loader));
75+ let syntax = Syntax::new(&doc, highlight_config, std::sync::Arc::new(loader)).unwrap();
76 let indent_query = language_config.indent_query().unwrap();
76 let indent_query = language_config.indent_query().unwrap();
77 let text = doc.slice(..);
77 let text = doc.slice(..);
78
78
helix-term/src/ui/markdown.rs+1−1
@@ -51,7 +51,7 @@ pub fn highlighted_code_block<'a>(
51 language.into(),
51 language.into(),
52 ))
52 ))
53 .and_then(|config| config.highlight_config(theme.scopes()))
53 .and_then(|config| config.highlight_config(theme.scopes()))
54− .map(|config| Syntax::new(&rope, config, Arc::clone(&config_loader)));
54+ .and_then(|config| Syntax::new(&rope, config, Arc::clone(&config_loader)));
55
55
56 let syntax = match syntax {
56 let syntax = match syntax {
57 Some(s) => s,
57 Some(s) => s,
helix-term/src/ui/picker.rs−3
@@ -240,12 +240,10 @@ impl<T: Item + 'static> FilePicker<T> {
240 log::info!("highlighting picker item failed");
240 log::info!("highlighting picker item failed");
241 return
241 return
242 };
242 };
243− log::info!("hmm1");
244 let Some(Overlay { content: picker, .. }) = compositor.find::<Overlay<Self>>() else {
243 let Some(Overlay { content: picker, .. }) = compositor.find::<Overlay<Self>>() else {
245 log::info!("picker closed before syntax highlighting finished");
244 log::info!("picker closed before syntax highlighting finished");
246 return
245 return
247 };
246 };
248− log::info!("hmm2");
249 // Try to find a document in the cache
247 // Try to find a document in the cache
250 let doc = match current_file {
248 let doc = match current_file {
251 PathOrId::Id(doc_id) => doc_mut!(editor, &doc_id),
249 PathOrId::Id(doc_id) => doc_mut!(editor, &doc_id),
@@ -254,7 +252,6 @@ impl<T: Item + 'static> FilePicker<T> {
254 _ => return,
252 _ => return,
255 },
253 },
256 };
254 };
257− log::info!("yay");
258 doc.syntax = Some(syntax);
255 doc.syntax = Some(syntax);
259 };
256 };
260 Callback::EditorCompositor(Box::new(callback))
257 Callback::EditorCompositor(Box::new(callback))
helix-view/src/document.rs+6−5
@@ -972,8 +972,7 @@ impl Document {
972 ) {
972 ) {
973 if let (Some(language_config), Some(loader)) = (language_config, loader) {
973 if let (Some(language_config), Some(loader)) = (language_config, loader) {
974 if let Some(highlight_config) = language_config.highlight_config(&loader.scopes()) {
974 if let Some(highlight_config) = language_config.highlight_config(&loader.scopes()) {
975− let syntax = Syntax::new(&self.text, highlight_config, loader);
975+ self.syntax = Syntax::new(&self.text, highlight_config, loader);
976− self.syntax = Some(syntax);
977 }
976 }
978
977
979 self.language = Some(language_config);
978 self.language = Some(language_config);
@@ -1113,9 +1112,11 @@ impl Document {
1113 // update tree-sitter syntax tree
1112 // update tree-sitter syntax tree
1114 if let Some(syntax) = &mut self.syntax {
1113 if let Some(syntax) = &mut self.syntax {
1115 // TODO: no unwrap
1114 // TODO: no unwrap
1116− syntax
1117− .update(&old_doc, &self.text, transaction.changes())
1115+ let res = syntax.update(&old_doc, &self.text, transaction.changes());
1118− .unwrap();
1116+ if res.is_err() {
1117+ log::error!("TS parser failed, disabeling TS for the current buffer: {res:?}");
1118+ self.syntax = None;
1119+ }
1119 }
1120 }
1120
1121
1121 let changes = transaction.changes();
1122 let changes = transaction.changes();