From 13110f48e948d7554500aefc336e72f96041386b Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Tue, 28 Aug 2018 00:42:13 +0300
Subject: [PATCH] Log errors

---
 crates/libanalysis/src/lib.rs            | 12 ++++++++++--
 crates/libsyntax2/src/parser_impl/mod.rs | 10 ++++++++++
 crates/server/src/main.rs                |  2 +-
 3 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/crates/libanalysis/src/lib.rs b/crates/libanalysis/src/lib.rs
index 7a34d354ef6..fe2c3c2e6ae 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 f60ef80f093..b343b404fda 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<Event>,
+    steps: Cell<u32>,
 }
 
 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 5e4c0fe7e53..615dd082c74 100644
--- a/crates/server/src/main.rs
+++ b/crates/server/src/main.rs
@@ -40,7 +40,7 @@ use ::{
 pub type Result<T> = ::std::result::Result<T, ::failure::Error>;
 
 fn main() -> Result<()> {
-    Logger::with_env()
+    Logger::with_env_or_str("m=error")
         .duplicate_to_stderr(Duplicate::All)
         .log_to_file()
         .directory("log")