1
1
use :: serde:: { Deserialize , Serialize } ;
2
2
use anyhow:: Context as _;
3
- use gpui:: { App , Entity , Task , WeakEntity } ;
4
- use language:: ServerHealth ;
5
- use lsp:: { LanguageServer , LanguageServerName } ;
3
+ use gpui:: { App , AsyncApp , Entity , Task , WeakEntity } ;
4
+ use language:: { Buffer , ServerHealth } ;
5
+ use lsp:: { LanguageServer , LanguageServerId , LanguageServerName } ;
6
6
use rpc:: proto;
7
7
8
8
use crate :: { LspStore , LspStoreEvent , Project , ProjectPath , lsp_store} ;
@@ -83,31 +83,32 @@ pub fn register_notifications(lsp_store: WeakEntity<LspStore>, language_server:
83
83
84
84
pub fn cancel_flycheck (
85
85
project : Entity < Project > ,
86
- buffer_path : ProjectPath ,
86
+ buffer_path : Option < ProjectPath > ,
87
87
cx : & mut App ,
88
88
) -> Task < anyhow:: Result < ( ) > > {
89
89
let upstream_client = project. read ( cx) . lsp_store ( ) . read ( cx) . upstream_client ( ) ;
90
90
let lsp_store = project. read ( cx) . lsp_store ( ) ;
91
- let buffer = project. update ( cx, |project, cx| {
92
- project. buffer_store ( ) . update ( cx, |buffer_store, cx| {
93
- buffer_store. open_buffer ( buffer_path, cx)
91
+ let buffer = buffer_path. map ( |buffer_path| {
92
+ project. update ( cx, |project, cx| {
93
+ project. buffer_store ( ) . update ( cx, |buffer_store, cx| {
94
+ buffer_store. open_buffer ( buffer_path, cx)
95
+ } )
94
96
} )
95
97
} ) ;
96
98
97
99
cx. spawn ( async move |cx| {
98
- let buffer = buffer. await ?;
99
- let Some ( rust_analyzer_server) = project. read_with ( cx, |project, cx| {
100
- project. language_server_id_for_name ( buffer. read ( cx) , & RUST_ANALYZER_NAME , cx)
101
- } ) ?
100
+ let buffer = match buffer {
101
+ Some ( buffer) => Some ( buffer. await ?) ,
102
+ None => None ,
103
+ } ;
104
+ let Some ( rust_analyzer_server) = find_rust_analyzer_server ( & project, buffer. as_ref ( ) , cx)
102
105
else {
103
106
return Ok ( ( ) ) ;
104
107
} ;
105
- let buffer_id = buffer. read_with ( cx, |buffer, _| buffer. remote_id ( ) . to_proto ( ) ) ?;
106
108
107
109
if let Some ( ( client, project_id) ) = upstream_client {
108
110
let request = proto:: LspExtCancelFlycheck {
109
111
project_id,
110
- buffer_id,
111
112
language_server_id : rust_analyzer_server. to_proto ( ) ,
112
113
} ;
113
114
client
@@ -130,28 +131,33 @@ pub fn cancel_flycheck(
130
131
131
132
pub fn run_flycheck (
132
133
project : Entity < Project > ,
133
- buffer_path : ProjectPath ,
134
+ buffer_path : Option < ProjectPath > ,
134
135
cx : & mut App ,
135
136
) -> Task < anyhow:: Result < ( ) > > {
136
137
let upstream_client = project. read ( cx) . lsp_store ( ) . read ( cx) . upstream_client ( ) ;
137
138
let lsp_store = project. read ( cx) . lsp_store ( ) ;
138
- let buffer = project. update ( cx, |project, cx| {
139
- project. buffer_store ( ) . update ( cx, |buffer_store, cx| {
140
- buffer_store. open_buffer ( buffer_path, cx)
139
+ let buffer = buffer_path. map ( |buffer_path| {
140
+ project. update ( cx, |project, cx| {
141
+ project. buffer_store ( ) . update ( cx, |buffer_store, cx| {
142
+ buffer_store. open_buffer ( buffer_path, cx)
143
+ } )
141
144
} )
142
145
} ) ;
143
146
144
147
cx. spawn ( async move |cx| {
145
- let buffer = buffer. await ?;
146
- let Some ( rust_analyzer_server) = project. read_with ( cx, |project, cx| {
147
- project. language_server_id_for_name ( buffer. read ( cx) , & RUST_ANALYZER_NAME , cx)
148
- } ) ?
148
+ let buffer = match buffer {
149
+ Some ( buffer) => Some ( buffer. await ?) ,
150
+ None => None ,
151
+ } ;
152
+ let Some ( rust_analyzer_server) = find_rust_analyzer_server ( & project, buffer. as_ref ( ) , cx)
149
153
else {
150
154
return Ok ( ( ) ) ;
151
155
} ;
152
- let buffer_id = buffer. read_with ( cx, |buffer, _| buffer. remote_id ( ) . to_proto ( ) ) ?;
153
156
154
157
if let Some ( ( client, project_id) ) = upstream_client {
158
+ let buffer_id = buffer
159
+ . map ( |buffer| buffer. read_with ( cx, |buffer, _| buffer. remote_id ( ) . to_proto ( ) ) )
160
+ . transpose ( ) ?;
155
161
let request = proto:: LspExtRunFlycheck {
156
162
project_id,
157
163
buffer_id,
@@ -182,31 +188,32 @@ pub fn run_flycheck(
182
188
183
189
pub fn clear_flycheck (
184
190
project : Entity < Project > ,
185
- buffer_path : ProjectPath ,
191
+ buffer_path : Option < ProjectPath > ,
186
192
cx : & mut App ,
187
193
) -> Task < anyhow:: Result < ( ) > > {
188
194
let upstream_client = project. read ( cx) . lsp_store ( ) . read ( cx) . upstream_client ( ) ;
189
195
let lsp_store = project. read ( cx) . lsp_store ( ) ;
190
- let buffer = project. update ( cx, |project, cx| {
191
- project. buffer_store ( ) . update ( cx, |buffer_store, cx| {
192
- buffer_store. open_buffer ( buffer_path, cx)
196
+ let buffer = buffer_path. map ( |buffer_path| {
197
+ project. update ( cx, |project, cx| {
198
+ project. buffer_store ( ) . update ( cx, |buffer_store, cx| {
199
+ buffer_store. open_buffer ( buffer_path, cx)
200
+ } )
193
201
} )
194
202
} ) ;
195
203
196
204
cx. spawn ( async move |cx| {
197
- let buffer = buffer. await ?;
198
- let Some ( rust_analyzer_server) = project. read_with ( cx, |project, cx| {
199
- project. language_server_id_for_name ( buffer. read ( cx) , & RUST_ANALYZER_NAME , cx)
200
- } ) ?
205
+ let buffer = match buffer {
206
+ Some ( buffer) => Some ( buffer. await ?) ,
207
+ None => None ,
208
+ } ;
209
+ let Some ( rust_analyzer_server) = find_rust_analyzer_server ( & project, buffer. as_ref ( ) , cx)
201
210
else {
202
211
return Ok ( ( ) ) ;
203
212
} ;
204
- let buffer_id = buffer. read_with ( cx, |buffer, _| buffer. remote_id ( ) . to_proto ( ) ) ?;
205
213
206
214
if let Some ( ( client, project_id) ) = upstream_client {
207
215
let request = proto:: LspExtClearFlycheck {
208
216
project_id,
209
- buffer_id,
210
217
language_server_id : rust_analyzer_server. to_proto ( ) ,
211
218
} ;
212
219
client
@@ -226,3 +233,40 @@ pub fn clear_flycheck(
226
233
anyhow:: Ok ( ( ) )
227
234
} )
228
235
}
236
+
237
+ fn find_rust_analyzer_server (
238
+ project : & Entity < Project > ,
239
+ buffer : Option < & Entity < Buffer > > ,
240
+ cx : & mut AsyncApp ,
241
+ ) -> Option < LanguageServerId > {
242
+ project
243
+ . read_with ( cx, |project, cx| {
244
+ buffer
245
+ . and_then ( |buffer| {
246
+ project. language_server_id_for_name ( buffer. read ( cx) , & RUST_ANALYZER_NAME , cx)
247
+ } )
248
+ // If no rust-analyzer found for the current buffer (e.g. `settings.json`), fall back to the project lookup
249
+ // and use project's rust-analyzer if it's the only one.
250
+ . or_else ( || {
251
+ let rust_analyzer_servers = project
252
+ . lsp_store ( )
253
+ . read ( cx)
254
+ . language_server_statuses
255
+ . iter ( )
256
+ . filter_map ( |( server_id, server_status) | {
257
+ if server_status. name == RUST_ANALYZER_NAME {
258
+ Some ( * server_id)
259
+ } else {
260
+ None
261
+ }
262
+ } )
263
+ . collect :: < Vec < _ > > ( ) ;
264
+ if rust_analyzer_servers. len ( ) == 1 {
265
+ rust_analyzer_servers. first ( ) . copied ( )
266
+ } else {
267
+ None
268
+ }
269
+ } )
270
+ } )
271
+ . ok ( ) ?
272
+ }
0 commit comments