3
3
use std:: {
4
4
io:: { self , BufRead , BufReader , Read , Write } ,
5
5
process:: { Child , ChildStdin , ChildStdout , Command , Stdio } ,
6
- sync:: Arc ,
6
+ sync:: { Arc , Mutex } ,
7
7
} ;
8
8
9
9
use paths:: AbsPath ;
@@ -17,13 +17,20 @@ use crate::{
17
17
18
18
#[ derive( Debug ) ]
19
19
pub ( crate ) struct ProcMacroProcessSrv {
20
+ /// The state of the proc-macro server process, the protocol is currently strictly sequential
21
+ /// hence the lock on the state.
22
+ state : Mutex < ProcessSrvState > ,
23
+ version : u32 ,
24
+ mode : SpanMode ,
25
+ }
26
+
27
+ #[ derive( Debug ) ]
28
+ struct ProcessSrvState {
20
29
process : Process ,
21
30
stdin : ChildStdin ,
22
31
stdout : BufReader < ChildStdout > ,
23
32
/// Populated when the server exits.
24
33
server_exited : Option < ServerError > ,
25
- version : u32 ,
26
- mode : SpanMode ,
27
34
}
28
35
29
36
impl ProcMacroProcessSrv {
@@ -36,10 +43,7 @@ impl ProcMacroProcessSrv {
36
43
let ( stdin, stdout) = process. stdio ( ) . expect ( "couldn't access child stdio" ) ;
37
44
38
45
io:: Result :: Ok ( ProcMacroProcessSrv {
39
- process,
40
- stdin,
41
- stdout,
42
- server_exited : None ,
46
+ state : Mutex :: new ( ProcessSrvState { process, stdin, stdout, server_exited : None } ) ,
43
47
version : 0 ,
44
48
mode : SpanMode :: Id ,
45
49
} )
@@ -76,7 +80,7 @@ impl ProcMacroProcessSrv {
76
80
self . version
77
81
}
78
82
79
- pub ( crate ) fn version_check ( & mut self ) -> Result < u32 , ServerError > {
83
+ fn version_check ( & self ) -> Result < u32 , ServerError > {
80
84
let request = Request :: ApiVersionCheck { } ;
81
85
let response = self . send_task ( request) ?;
82
86
@@ -86,7 +90,7 @@ impl ProcMacroProcessSrv {
86
90
}
87
91
}
88
92
89
- fn enable_rust_analyzer_spans ( & mut self ) -> Result < SpanMode , ServerError > {
93
+ fn enable_rust_analyzer_spans ( & self ) -> Result < SpanMode , ServerError > {
90
94
let request = Request :: SetConfig ( crate :: msg:: ServerConfig {
91
95
span_mode : crate :: msg:: SpanMode :: RustAnalyzer ,
92
96
} ) ;
@@ -99,7 +103,7 @@ impl ProcMacroProcessSrv {
99
103
}
100
104
101
105
pub ( crate ) fn find_proc_macros (
102
- & mut self ,
106
+ & self ,
103
107
dylib_path : & AbsPath ,
104
108
) -> Result < Result < Vec < ( String , ProcMacroKind ) > , String > , ServerError > {
105
109
let request = Request :: ListMacros { dylib_path : dylib_path. to_path_buf ( ) . into ( ) } ;
@@ -112,28 +116,29 @@ impl ProcMacroProcessSrv {
112
116
}
113
117
}
114
118
115
- pub ( crate ) fn send_task ( & mut self , req : Request ) -> Result < Response , ServerError > {
116
- if let Some ( server_error) = & self . server_exited {
119
+ pub ( crate ) fn send_task ( & self , req : Request ) -> Result < Response , ServerError > {
120
+ let state = & mut * self . state . lock ( ) . unwrap ( ) ;
121
+ if let Some ( server_error) = & state. server_exited {
117
122
return Err ( server_error. clone ( ) ) ;
118
123
}
119
124
120
125
let mut buf = String :: new ( ) ;
121
- send_request ( & mut self . stdin , & mut self . stdout , req, & mut buf) . map_err ( |e| {
126
+ send_request ( & mut state . stdin , & mut state . stdout , req, & mut buf) . map_err ( |e| {
122
127
if e. io . as_ref ( ) . map ( |it| it. kind ( ) ) == Some ( io:: ErrorKind :: BrokenPipe ) {
123
- match self . process . child . try_wait ( ) {
128
+ match state . process . child . try_wait ( ) {
124
129
Ok ( None ) => e,
125
130
Ok ( Some ( status) ) => {
126
131
let mut msg = String :: new ( ) ;
127
132
if !status. success ( ) {
128
- if let Some ( stderr) = self . process . child . stderr . as_mut ( ) {
133
+ if let Some ( stderr) = state . process . child . stderr . as_mut ( ) {
129
134
_ = stderr. read_to_string ( & mut msg) ;
130
135
}
131
136
}
132
137
let server_error = ServerError {
133
138
message : format ! ( "server exited with {status}: {msg}" ) ,
134
139
io : None ,
135
140
} ;
136
- self . server_exited = Some ( server_error. clone ( ) ) ;
141
+ state . server_exited = Some ( server_error. clone ( ) ) ;
137
142
server_error
138
143
}
139
144
Err ( _) => e,
0 commit comments