1- //! A visitor for downcasting arbitrary request (JSON) into a specific type .
1+ //! See [RequestDispatcher] .
22use std:: { fmt, panic, thread} ;
33
44use serde:: { de:: DeserializeOwned , Serialize } ;
@@ -10,14 +10,30 @@ use crate::{
1010 LspError , Result ,
1111} ;
1212
13+ /// A visitor for routing a raw JSON request to an appropriate handler function.
14+ ///
15+ /// Most requests are read-only and async and are handled on the threadpool
16+ /// (`on` method).
17+ ///
18+ /// Some read-only requests are latency sensitive, and are immediately handled
19+ /// on the main loop thread (`on_sync`). These are typically typing-related
20+ /// requests.
21+ ///
22+ /// Some requests modify the state, and are run on the main thread to get
23+ /// `&mut` (`on_sync_mut`).
24+ ///
25+ /// Read-only requests are wrapped into `catch_unwind` -- they don't modify the
26+ /// state, so it's OK to recover from their failures.
1327pub ( crate ) struct RequestDispatcher < ' a > {
1428 pub ( crate ) req : Option < lsp_server:: Request > ,
1529 pub ( crate ) global_state : & ' a mut GlobalState ,
1630}
1731
1832impl < ' a > RequestDispatcher < ' a > {
19- /// Dispatches the request onto the current thread
20- pub ( crate ) fn on_sync < R > (
33+ /// Dispatches the request onto the current thread, given full access to
34+ /// mutable global state. Unlike all other methods here, this one isn't
35+ /// guarded by `catch_unwind`, so, please, don't make bugs :-)
36+ pub ( crate ) fn on_sync_mut < R > (
2137 & mut self ,
2238 f : fn ( & mut GlobalState , R :: Params ) -> Result < R :: Result > ,
2339 ) -> Result < & mut Self >
@@ -26,26 +42,40 @@ impl<'a> RequestDispatcher<'a> {
2642 R :: Params : DeserializeOwned + panic:: UnwindSafe + fmt:: Debug + ' static ,
2743 R :: Result : Serialize + ' static ,
2844 {
29- let ( id, params) = match self . parse :: < R > ( ) {
45+ let ( id, params, panic_context ) = match self . parse :: < R > ( ) {
3046 Some ( it) => it,
3147 None => return Ok ( self ) ,
3248 } ;
33- let global_state = panic:: AssertUnwindSafe ( & mut * self . global_state ) ;
49+ let _pctx = stdx:: panic_context:: enter ( panic_context) ;
50+
51+ let result = f ( & mut self . global_state , params) ;
52+ let response = result_to_response :: < R > ( id, result) ;
53+
54+ self . global_state . respond ( response) ;
55+ Ok ( self )
56+ }
57+
58+ /// Dispatches the request onto the current thread.
59+ pub ( crate ) fn on_sync < R > (
60+ & mut self ,
61+ f : fn ( GlobalStateSnapshot , R :: Params ) -> Result < R :: Result > ,
62+ ) -> Result < & mut Self >
63+ where
64+ R : lsp_types:: request:: Request + ' static ,
65+ R :: Params : DeserializeOwned + panic:: UnwindSafe + fmt:: Debug + ' static ,
66+ R :: Result : Serialize + ' static ,
67+ {
68+ let ( id, params, panic_context) = match self . parse :: < R > ( ) {
69+ Some ( it) => it,
70+ None => return Ok ( self ) ,
71+ } ;
72+ let global_state_snapshot = self . global_state . snapshot ( ) ;
3473
3574 let result = panic:: catch_unwind ( move || {
36- // Make sure that the whole AssertUnwindSafe is moved into the
37- // closure, and not just its field.
38- let panic:: AssertUnwindSafe ( global_state) = { global_state } ;
39-
40- let _pctx = stdx:: panic_context:: enter ( format ! (
41- "\n version: {}\n request: {} {:#?}" ,
42- env!( "REV" ) ,
43- R :: METHOD ,
44- params
45- ) ) ;
46- f ( global_state, params)
75+ let _pctx = stdx:: panic_context:: enter ( panic_context) ;
76+ f ( global_state_snapshot, params)
4777 } ) ;
48- let response = result_to_response :: < R > ( id, result) ;
78+ let response = thread_result_to_response :: < R > ( id, result) ;
4979
5080 self . global_state . respond ( response) ;
5181 Ok ( self )
@@ -61,7 +91,7 @@ impl<'a> RequestDispatcher<'a> {
6191 R :: Params : DeserializeOwned + panic:: UnwindSafe + Send + fmt:: Debug + ' static ,
6292 R :: Result : Serialize + ' static ,
6393 {
64- let ( id, params) = match self . parse :: < R > ( ) {
94+ let ( id, params, panic_context ) = match self . parse :: < R > ( ) {
6595 Some ( it) => it,
6696 None => return self ,
6797 } ;
@@ -70,15 +100,10 @@ impl<'a> RequestDispatcher<'a> {
70100 let world = self . global_state . snapshot ( ) ;
71101 move || {
72102 let result = panic:: catch_unwind ( move || {
73- let _pctx = stdx:: panic_context:: enter ( format ! (
74- "\n version: {}\n request: {} {:#?}" ,
75- env!( "REV" ) ,
76- R :: METHOD ,
77- params
78- ) ) ;
103+ let _pctx = stdx:: panic_context:: enter ( panic_context) ;
79104 f ( world, params)
80105 } ) ;
81- let response = result_to_response :: < R > ( id, result) ;
106+ let response = thread_result_to_response :: < R > ( id, result) ;
82107 Task :: Response ( response)
83108 }
84109 } ) ;
@@ -98,10 +123,10 @@ impl<'a> RequestDispatcher<'a> {
98123 }
99124 }
100125
101- fn parse < R > ( & mut self ) -> Option < ( lsp_server:: RequestId , R :: Params ) >
126+ fn parse < R > ( & mut self ) -> Option < ( lsp_server:: RequestId , R :: Params , String ) >
102127 where
103128 R : lsp_types:: request:: Request + ' static ,
104- R :: Params : DeserializeOwned + ' static ,
129+ R :: Params : DeserializeOwned + fmt :: Debug + ' static ,
105130 {
106131 let req = match & self . req {
107132 Some ( req) if req. method == R :: METHOD => self . req . take ( ) . unwrap ( ) ,
@@ -110,7 +135,11 @@ impl<'a> RequestDispatcher<'a> {
110135
111136 let res = crate :: from_json ( R :: METHOD , req. params ) ;
112137 match res {
113- Ok ( params) => Some ( ( req. id , params) ) ,
138+ Ok ( params) => {
139+ let panic_context =
140+ format ! ( "\n version: {}\n request: {} {:#?}" , env!( "REV" ) , R :: METHOD , params) ;
141+ Some ( ( req. id , params, panic_context) )
142+ }
114143 Err ( err) => {
115144 let response = lsp_server:: Response :: new_err (
116145 req. id ,
@@ -124,7 +153,7 @@ impl<'a> RequestDispatcher<'a> {
124153 }
125154}
126155
127- fn result_to_response < R > (
156+ fn thread_result_to_response < R > (
128157 id : lsp_server:: RequestId ,
129158 result : thread:: Result < Result < R :: Result > > ,
130159) -> lsp_server:: Response
@@ -134,8 +163,37 @@ where
134163 R :: Result : Serialize + ' static ,
135164{
136165 match result {
137- Ok ( Ok ( resp) ) => lsp_server:: Response :: new_ok ( id, & resp) ,
138- Ok ( Err ( e) ) => match e. downcast :: < LspError > ( ) {
166+ Ok ( result) => result_to_response :: < R > ( id, result) ,
167+ Err ( panic) => {
168+ let mut message = "server panicked" . to_string ( ) ;
169+
170+ let panic_message = panic
171+ . downcast_ref :: < String > ( )
172+ . map ( String :: as_str)
173+ . or_else ( || panic. downcast_ref :: < & str > ( ) . copied ( ) ) ;
174+
175+ if let Some ( panic_message) = panic_message {
176+ message. push_str ( ": " ) ;
177+ message. push_str ( panic_message)
178+ } ;
179+
180+ lsp_server:: Response :: new_err ( id, lsp_server:: ErrorCode :: InternalError as i32 , message)
181+ }
182+ }
183+ }
184+
185+ fn result_to_response < R > (
186+ id : lsp_server:: RequestId ,
187+ result : Result < R :: Result > ,
188+ ) -> lsp_server:: Response
189+ where
190+ R : lsp_types:: request:: Request + ' static ,
191+ R :: Params : DeserializeOwned + ' static ,
192+ R :: Result : Serialize + ' static ,
193+ {
194+ match result {
195+ Ok ( resp) => lsp_server:: Response :: new_ok ( id, & resp) ,
196+ Err ( e) => match e. downcast :: < LspError > ( ) {
139197 Ok ( lsp_error) => lsp_server:: Response :: new_err ( id, lsp_error. code , lsp_error. message ) ,
140198 Err ( e) => {
141199 if is_cancelled ( & * e) {
@@ -153,21 +211,6 @@ where
153211 }
154212 }
155213 } ,
156- Err ( panic) => {
157- let mut message = "server panicked" . to_string ( ) ;
158-
159- let panic_message = panic
160- . downcast_ref :: < String > ( )
161- . map ( String :: as_str)
162- . or_else ( || panic. downcast_ref :: < & str > ( ) . copied ( ) ) ;
163-
164- if let Some ( panic_message) = panic_message {
165- message. push_str ( ": " ) ;
166- message. push_str ( panic_message)
167- } ;
168-
169- lsp_server:: Response :: new_err ( id, lsp_server:: ErrorCode :: InternalError as i32 , message)
170- }
171214 }
172215}
173216
0 commit comments