diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs index 7a34d354ef..fe2c3c2e6a 100644 --- a/crates/libanalysis/src/lib.rs +++ b/crates/libanalysis/src/lib.rs @@ -15,6 +15,7 @@ mod module_map; use std::{ fmt, path::{Path, PathBuf}, + panic, sync::{ Arc, atomic::{AtomicBool, Ordering::SeqCst}, @@ -307,8 +308,15 @@ impl FileData { } fn syntax(&self) -> &File { - self.syntax - .get_or_init(|| File::parse(&self.text)) + let text = &self.text; + let syntax = &self.syntax; + match panic::catch_unwind(panic::AssertUnwindSafe(|| syntax.get_or_init(|| File::parse(text)))) { + Ok(file) => file, + Err(err) => { + error!("Parser paniced on:\n------\n{}\n------\n", &self.text); + panic::resume_unwind(err) + } + } } fn syntax_transient(&self) -> File { diff --git a/crates/libsyntax2/src/parser_impl/mod.rs b/crates/libsyntax2/src/parser_impl/mod.rs index f60ef80f09..b343b404fd 100644 --- a/crates/libsyntax2/src/parser_impl/mod.rs +++ b/crates/libsyntax2/src/parser_impl/mod.rs @@ -1,6 +1,8 @@ mod event; mod input; +use std::cell::Cell; + use { lexer::Token, parser_api::Parser, @@ -51,6 +53,7 @@ pub(crate) struct ParserImpl<'t> { pos: InputPosition, events: Vec, + steps: Cell, } impl<'t> ParserImpl<'t> { @@ -60,6 +63,7 @@ impl<'t> ParserImpl<'t> { pos: InputPosition::new(), events: Vec::new(), + steps: Cell::new(0), } } @@ -91,6 +95,12 @@ impl<'t> ParserImpl<'t> { } pub(super) fn nth(&self, n: u32) -> SyntaxKind { + let steps = self.steps.get(); + if steps > 10_000_000 { + panic!("the parser seems stuck"); + } + self.steps.set(steps + 1); + self.inp.kind(self.pos + n) } diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index 5e4c0fe7e5..615dd082c7 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -40,7 +40,7 @@ use ::{ pub type Result = ::std::result::Result; fn main() -> Result<()> { - Logger::with_env() + Logger::with_env_or_str("m=error") .duplicate_to_stderr(Duplicate::All) .log_to_file() .directory("log")