1
- use std:: sync:: Arc ;
2
-
3
1
use notification:: ShowMessage ;
4
2
use pg_commands:: CommandType ;
5
- use pg_workspace:: Workspace ;
6
3
use tokio:: sync:: RwLock ;
7
4
use tower_lsp:: jsonrpc;
8
5
use tower_lsp:: lsp_types:: * ;
9
6
use tower_lsp:: { Client , LanguageServer } ;
10
7
11
8
use crate :: client:: client_flags:: ClientFlags ;
12
- use crate :: db_connection:: DbConnection ;
13
9
use crate :: server:: options:: ClientConfigurationOptions ;
10
+ use crate :: utils:: file_path;
11
+ use crate :: utils:: normalize_uri;
12
+ use crate :: workspace_handler:: WorkspaceHandler ;
14
13
15
14
struct Server {
16
15
client : Client ,
17
- db : RwLock < Option < DbConnection > > ,
18
- ide : Arc < RwLock < Workspace > > ,
16
+ workspace_handler : WorkspaceHandler ,
19
17
client_capabilities : RwLock < Option < ClientFlags > > ,
20
18
}
21
19
22
20
impl Server {
23
21
pub async fn new ( client : Client ) -> Self {
24
- let ide = Arc :: new ( RwLock :: new ( Workspace :: new ( ) ) ) ;
25
22
Self {
26
23
client,
27
- db : RwLock :: new ( None ) ,
28
- ide,
24
+ workspace_handler : WorkspaceHandler :: new ( ) ,
29
25
client_capabilities : RwLock :: new ( None ) ,
30
26
}
31
27
}
@@ -54,46 +50,6 @@ impl Server {
54
50
}
55
51
}
56
52
57
- /// `update_db_connection` will update `Self`'s database connection.
58
- /// If the passed-in connection string is the same that we're already connected to, it's a noop.
59
- /// Otherwise, it'll first open a new connection, replace `Self`'s connection, and then close
60
- /// the old one.
61
- async fn update_db_connection (
62
- & self ,
63
- options : ClientConfigurationOptions ,
64
- ) -> anyhow:: Result < ( ) > {
65
- if options. db_connection_string . is_none ( )
66
- || self
67
- . db
68
- . read ( )
69
- . await
70
- . as_ref ( )
71
- // if the connection is already connected to the same database, do nothing
72
- . is_some_and ( |c| c. connected_to ( options. db_connection_string . as_ref ( ) . unwrap ( ) ) )
73
- {
74
- return Ok ( ( ) ) ;
75
- }
76
-
77
- let connection_string = options. db_connection_string . unwrap ( ) ;
78
-
79
- let mut db = DbConnection :: new ( connection_string) . await ?;
80
-
81
- let ide = self . ide . clone ( ) ;
82
- db. listen_for_schema_updates ( move |schema| {
83
- let _guard = ide. blocking_write ( ) . set_schema_cache ( schema) ;
84
- } ) ;
85
-
86
- let mut current_db = self . db . blocking_write ( ) ;
87
- let old_db = current_db. replace ( db) ;
88
-
89
- if old_db. is_some ( ) {
90
- let old_db = old_db. unwrap ( ) ;
91
- old_db. close ( ) . await ;
92
- }
93
-
94
- Ok ( ( ) )
95
- }
96
-
97
53
async fn request_opts_from_client ( & self ) -> Option < ClientConfigurationOptions > {
98
54
let params = ConfigurationParams {
99
55
items : vec ! [ ConfigurationItem {
@@ -130,6 +86,30 @@ impl Server {
130
86
}
131
87
}
132
88
}
89
+
90
+ async fn publish_diagnostics ( & self , mut uri : Url ) -> anyhow:: Result < ( ) > {
91
+ normalize_uri ( & mut uri) ;
92
+
93
+ let diagnostics = self
94
+ . workspace_handler
95
+ . get_diagnostics ( file_path ( & uri) )
96
+ . await ;
97
+
98
+ self . client
99
+ . send_notification :: < ShowMessage > ( ShowMessageParams {
100
+ typ : MessageType :: INFO ,
101
+ message : format ! ( "diagnostics {}" , diagnostics. len( ) ) ,
102
+ } )
103
+ . await ;
104
+
105
+ let params = PublishDiagnosticsParams {
106
+ uri,
107
+ diagnostics,
108
+ version : None ,
109
+ } ;
110
+
111
+ Ok ( ( ) )
112
+ }
133
113
}
134
114
135
115
#[ tower_lsp:: async_trait]
@@ -186,16 +166,24 @@ impl LanguageServer for Server {
186
166
187
167
if capabilities. as_ref ( ) . unwrap ( ) . supports_pull_opts {
188
168
let opts = self . request_opts_from_client ( ) . await ;
189
- if opts. is_some ( ) {
190
- self . update_db_connection ( opts. unwrap ( ) ) . await ;
169
+ if opts
170
+ . as_ref ( )
171
+ . is_some_and ( |o| o. db_connection_string . is_some ( ) )
172
+ {
173
+ let conn_str = opts. unwrap ( ) . db_connection_string . unwrap ( ) ;
174
+ self . workspace_handler . change_db ( conn_str) . await ;
191
175
return ;
192
176
}
193
177
}
194
178
195
179
let opts = self . parse_options_from_client ( params. settings ) ;
196
180
197
- if opts. is_some ( ) {
198
- self . update_db_connection ( opts. unwrap ( ) ) . await ;
181
+ if opts
182
+ . as_ref ( )
183
+ . is_some_and ( |o| o. db_connection_string . is_some ( ) )
184
+ {
185
+ let conn_str = opts. unwrap ( ) . db_connection_string . unwrap ( ) ;
186
+ self . workspace_handler . change_db ( conn_str) . await ;
199
187
}
200
188
}
201
189
@@ -213,21 +201,12 @@ impl LanguageServer for Server {
213
201
let stmt = serde_json:: from_value ( params)
214
202
. map_err ( |_| jsonrpc:: Error :: invalid_request ( ) ) ?;
215
203
216
- let conn = self . db . read ( ) . await ;
217
- match conn
218
- . as_ref ( )
219
- . expect ( "No connection to the database." )
220
- . run_stmt ( stmt)
221
- . await
222
- {
223
- Ok ( pg_result) => {
204
+ match self . workspace_handler . run_stmt ( stmt) . await {
205
+ Ok ( rows_affected) => {
224
206
self . client
225
207
. send_notification :: < ShowMessage > ( ShowMessageParams {
226
208
typ : MessageType :: INFO ,
227
- message : format ! (
228
- "Success! Affected rows: {}" ,
229
- pg_result. rows_affected( )
230
- ) ,
209
+ message : format ! ( "Success! Affected rows: {}" , rows_affected) ,
231
210
} )
232
211
. await ;
233
212
}
0 commit comments