1#![allow(unused_variables, dead_code, unused_imports)]
2
3use std::time::UNIX_EPOCH;
11
12use serde_json::json;
13use tonic::{Request, Response, Status};
14use url::Url;
15use CommonLibrary::{
16 Command::CommandExecutor::CommandExecutor,
17 LanguageFeature::{
18 DTO::PositionDTO::PositionDTO,
19 LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
20 },
21};
22
23use crate::{
24 RPC::CocoonService::CocoonServiceImpl,
25 Vine::Generated::{GenericRequest as GenericRequestMsg, GenericResponse, RpcError},
26 dev_log,
27};
28
29pub async fn Fn(
30 Service:&CocoonServiceImpl,
31
32 request:Request<GenericRequestMsg>,
33) -> Result<Response<GenericResponse>, Status> {
34 let Req = request.into_inner();
35
36 let RequestId = Req.request_identifier;
37
38 dev_log!(
39 "cocoon",
40 "[CocoonService] generic request: method={} id={}",
41 Req.method,
42 RequestId
43 );
44
45 fn OkResponse(RequestId:u64, Value:&impl serde::Serialize) -> Response<GenericResponse> {
47 let Bytes = serde_json::to_vec(Value).unwrap_or_default();
48
49 Response::new(GenericResponse { request_identifier:RequestId, result:Bytes, error:None })
50 }
51
52 fn ErrResponse(RequestId:u64, Code:i32, Message:String) -> Response<GenericResponse> {
54 Response::new(GenericResponse {
55 request_identifier:RequestId,
56 result:Vec::new(),
57 error:Some(RpcError { code:Code, message:Message, data:Vec::new() }),
58 })
59 }
60
61 let Params:serde_json::Value = if Req.parameter.is_empty() {
63 serde_json::Value::Null
64 } else {
65 serde_json::from_slice(&Req.parameter).unwrap_or(serde_json::Value::Null)
66 };
67
68 match Req.method.as_str() {
69 "fs.readFile" | "file:read" => {
71 let Path = Params
72 .as_str()
73 .or_else(|| Params.get("path").and_then(|V| V.as_str()))
74 .unwrap_or("");
75
76 match tokio::fs::read(Path).await {
77 Ok(Content) => Ok(OkResponse(RequestId, &Content)),
78
79 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("fs.readFile: {}", Error))),
80 }
81 },
82
83 "fs.writeFile" | "file:write" => {
84 let Path = Params.get("path").and_then(|V| V.as_str()).unwrap_or("");
85
86 let Content:Vec<u8> = Params
87 .get("content")
88 .and_then(|V| V.as_array())
89 .map(|A| A.iter().filter_map(|B| B.as_u64().map(|N| N as u8)).collect())
90 .unwrap_or_default();
91
92 match tokio::fs::write(Path, &Content).await {
93 Ok(()) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
94
95 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("fs.writeFile: {}", Error))),
96 }
97 },
98
99 "fs.stat" | "file:stat" => {
100 let Path = Params
101 .as_str()
102 .or_else(|| Params.get("path").and_then(|V| V.as_str()))
103 .unwrap_or("");
104
105 match tokio::fs::metadata(Path).await {
106 Ok(Meta) => {
107 let Mtime = Meta
108 .modified()
109 .ok()
110 .and_then(|T| T.duration_since(UNIX_EPOCH).ok())
111 .map(|D| D.as_millis() as u64)
112 .unwrap_or(0);
113
114 Ok(OkResponse(
115 RequestId,
116 &json!({
117 "type": if Meta.is_dir() { 2 } else { 1 },
118 "is_file": Meta.is_file(),
119 "is_directory": Meta.is_dir(),
120 "size": Meta.len(),
121 "mtime": Mtime,
122 }),
123 ))
124 },
125
126 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("fs.stat: {}", Error))),
127 }
128 },
129
130 "fs.listDir" | "fs.readdir" | "file:readdir" => {
131 let Path = Params
132 .as_str()
133 .or_else(|| Params.get("path").and_then(|V| V.as_str()))
134 .unwrap_or("");
135
136 match tokio::fs::read_dir(Path).await {
137 Ok(mut Entries) => {
138 let mut Items:Vec<serde_json::Value> = Vec::new();
140
141 while let Ok(Some(Entry)) = Entries.next_entry().await {
142 if let Some(Name) = Entry.file_name().to_str() {
143 let IsDir = Entry.file_type().await.map(|T| T.is_dir()).unwrap_or(false);
144
145 Items.push(json!({ "name": Name, "type": if IsDir { 2u32 } else { 1u32 } }));
146 }
147 }
148
149 Ok(OkResponse(RequestId, &Items))
150 },
151
152 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("fs.listDir: {}", Error))),
153 }
154 },
155
156 "fs.createDir" | "file:mkdir" => {
157 let Path = Params
158 .as_str()
159 .or_else(|| Params.get("path").and_then(|V| V.as_str()))
160 .unwrap_or("");
161
162 match tokio::fs::create_dir_all(Path).await {
163 Ok(()) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
164
165 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("fs.createDir: {}", Error))),
166 }
167 },
168
169 "fs.delete" | "file:delete" => {
170 let Path = Params
171 .as_str()
172 .or_else(|| Params.get("path").and_then(|V| V.as_str()))
173 .unwrap_or("");
174
175 let Result = if std::path::Path::new(Path).is_dir() {
176 tokio::fs::remove_dir_all(Path).await
177 } else {
178 tokio::fs::remove_file(Path).await
179 };
180
181 match Result {
182 Ok(()) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
183
184 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("fs.delete: {}", Error))),
185 }
186 },
187
188 "fs.rename" | "file:move" => {
189 let From = Params.get("from").and_then(|V| V.as_str()).unwrap_or("");
190
191 let To = Params.get("to").and_then(|V| V.as_str()).unwrap_or("");
192
193 match tokio::fs::rename(From, To).await {
194 Ok(()) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
195
196 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("fs.rename: {}", Error))),
197 }
198 },
199
200 "commands.execute" => {
202 let CommandId = Params.get("id").and_then(|V| V.as_str()).unwrap_or("").to_string();
203
204 let Arg = Params.get("arg").cloned().unwrap_or(serde_json::Value::Null);
205
206 match Service.environment.ExecuteCommand(CommandId, Arg).await {
207 Ok(Value) => Ok(OkResponse(RequestId, &Value)),
208
209 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
210 }
211 },
212
213 "executeCommand" => {
215 let CommandId = Params.get("commandId").and_then(|V| V.as_str()).unwrap_or("").to_string();
216
217 let Arg = Params
218 .get("arguments")
219 .and_then(|A| A.as_array())
220 .and_then(|A| A.first())
221 .cloned()
222 .unwrap_or(serde_json::Value::Null);
223
224 match Service.environment.ExecuteCommand(CommandId, Arg).await {
225 Ok(Value) => Ok(OkResponse(RequestId, &json!({ "result": Value }))),
226
227 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
228 }
229 },
230
231 "unregisterCommand" => {
232 let ExtensionId = Params.get("extensionId").and_then(|V| V.as_str()).unwrap_or("").to_string();
233
234 let CommandId = Params.get("commandId").and_then(|V| V.as_str()).unwrap_or("").to_string();
235
236 match Service.environment.UnregisterCommand(ExtensionId, CommandId).await {
237 Ok(()) => Ok(OkResponse(RequestId, &json!({ "success": true }))),
238
239 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
240 }
241 },
242
243 "UserInterface.ShowOpenDialog" => {
245 use CommonLibrary::UserInterface::{
246 DTO::OpenDialogOptionsDTO::OpenDialogOptionsDTO,
247 UserInterfaceProvider::UserInterfaceProvider,
248 };
249
250 let Title = Params
251 .get(0)
252 .and_then(|V| V.get("title"))
253 .and_then(|T| T.as_str())
254 .map(|S| S.to_string());
255
256 let Options = OpenDialogOptionsDTO {
257 Base:CommonLibrary::UserInterface::DTO::DialogOptionsDTO::DialogOptionsDTO {
258 Title,
259 ..Default::default()
260 },
261 ..OpenDialogOptionsDTO::default()
262 };
263
264 match Service.environment.ShowOpenDialog(Some(Options)).await {
265 Ok(Some(Paths)) => {
266 let Uris:Vec<String> = Paths.iter().map(|P| format!("file://{}", P.display())).collect();
267
268 Ok(OkResponse(RequestId, &json!(Uris)))
269 },
270
271 Ok(None) => Ok(OkResponse(RequestId, &json!(serde_json::Value::Array(vec![])))),
272
273 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
274 }
275 },
276
277 "UserInterface.ShowSaveDialog" => {
278 use CommonLibrary::UserInterface::{
279 DTO::SaveDialogOptionsDTO::SaveDialogOptionsDTO,
280 UserInterfaceProvider::UserInterfaceProvider,
281 };
282
283 let Title = Params
284 .get(0)
285 .and_then(|V| V.get("title"))
286 .and_then(|T| T.as_str())
287 .map(|S| S.to_string());
288
289 let Options = SaveDialogOptionsDTO {
290 Base:CommonLibrary::UserInterface::DTO::DialogOptionsDTO::DialogOptionsDTO {
291 Title,
292 ..Default::default()
293 },
294 ..SaveDialogOptionsDTO::default()
295 };
296
297 match Service.environment.ShowSaveDialog(Some(Options)).await {
298 Ok(Some(Path)) => Ok(OkResponse(RequestId, &json!(format!("file://{}", Path.display())))),
299
300 Ok(None) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
301
302 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
303 }
304 },
305
306 "UserInterface.ShowInputBox" => {
307 use CommonLibrary::UserInterface::{
308 DTO::InputBoxOptionsDTO::InputBoxOptionsDTO,
309 UserInterfaceProvider::UserInterfaceProvider,
310 };
311
312 let Opts = Params.get(0);
313
314 let Options = InputBoxOptionsDTO {
315 Prompt:Opts
316 .and_then(|V| V.get("prompt"))
317 .and_then(|P| P.as_str())
318 .map(|S| S.to_string()),
319
320 PlaceHolder:Opts
321 .and_then(|V| V.get("placeHolder"))
322 .and_then(|P| P.as_str())
323 .map(|S| S.to_string()),
324
325 IsPassword:Some(Opts.and_then(|V| V.get("password")).and_then(|B| B.as_bool()).unwrap_or(false)),
326
327 Value:Opts
328 .and_then(|V| V.get("value"))
329 .and_then(|V| V.as_str())
330 .map(|S| S.to_string()),
331
332 Title:None,
333
334 IgnoreFocusOut:None,
335 };
336
337 match Service.environment.ShowInputBox(Some(Options)).await {
338 Ok(Some(Text)) => Ok(OkResponse(RequestId, &json!(Text))),
339
340 Ok(None) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
341
342 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
343 }
344 },
345
346 "openExternal" => {
348 use tauri::Emitter;
349
350 let Url = Params
351 .as_str()
352 .or_else(|| Params.get("url").and_then(|V| V.as_str()))
353 .unwrap_or("")
354 .to_string();
355
356 let _ = Service
358 .environment
359 .ApplicationHandle
360 .emit("sky://native/openExternal", json!({ "url": Url }));
361
362 Ok(OkResponse(RequestId, &json!({ "success": true })))
363 },
364
365 "showTextDocument" => {
367 use tauri::Emitter;
368
369 let Uri = Params
370 .get("uri")
371 .and_then(|V| V.get("value").or(Some(V)))
372 .and_then(|V| V.as_str())
373 .unwrap_or("")
374 .to_string();
375
376 let ViewColumn = Params.get("viewColumn").and_then(|V| V.as_i64()).map(|N| N + 2);
377
378 let PreserveFocus = Params.get("preserveFocus").and_then(|V| V.as_bool()).unwrap_or(false);
379
380 let _ = Service.environment.ApplicationHandle.emit(
381 "sky://editor/openDocument",
382 json!({ "uri": Uri, "viewColumn": ViewColumn, "preserveFocus": PreserveFocus }),
383 );
384
385 Ok(OkResponse(RequestId, &json!({ "success": true })))
386 },
387
388 "showInformation" => {
389 use CommonLibrary::UserInterface::{
390 DTO::MessageSeverity::MessageSeverity,
391 UserInterfaceProvider::UserInterfaceProvider,
392 };
393
394 let Message = Params.get("message").and_then(|V| V.as_str()).unwrap_or("").to_string();
395
396 let Items:Option<serde_json::Value> = Params
397 .get("items")
398 .cloned()
399 .filter(|V| V.is_array() && !V.as_array().unwrap().is_empty());
400
401 match Service.environment.ShowMessage(MessageSeverity::Info, Message, Items).await {
402 Ok(Some(Selected)) => Ok(OkResponse(RequestId, &json!({ "selectedItem": Selected }))),
403
404 Ok(None) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
405
406 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
407 }
408 },
409
410 "showWarning" => {
411 use CommonLibrary::UserInterface::{
412 DTO::MessageSeverity::MessageSeverity,
413 UserInterfaceProvider::UserInterfaceProvider,
414 };
415
416 let Message = Params.get("message").and_then(|V| V.as_str()).unwrap_or("").to_string();
417
418 let Items:Option<serde_json::Value> = Params
419 .get("items")
420 .cloned()
421 .filter(|V| V.is_array() && !V.as_array().unwrap().is_empty());
422
423 match Service.environment.ShowMessage(MessageSeverity::Warning, Message, Items).await {
424 Ok(Some(Selected)) => Ok(OkResponse(RequestId, &json!({ "selectedItem": Selected }))),
425
426 Ok(None) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
427
428 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
429 }
430 },
431
432 "showError" => {
433 use CommonLibrary::UserInterface::{
434 DTO::MessageSeverity::MessageSeverity,
435 UserInterfaceProvider::UserInterfaceProvider,
436 };
437
438 let Message = Params.get("message").and_then(|V| V.as_str()).unwrap_or("").to_string();
439
440 let Items:Option<serde_json::Value> = Params
441 .get("items")
442 .cloned()
443 .filter(|V| V.is_array() && !V.as_array().unwrap().is_empty());
444
445 match Service.environment.ShowMessage(MessageSeverity::Error, Message, Items).await {
446 Ok(Some(Selected)) => Ok(OkResponse(RequestId, &json!({ "selectedItem": Selected }))),
447
448 Ok(None) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
449
450 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
451 }
452 },
453
454 "createStatusBarItem" => {
455 use tauri::Emitter;
456
457 let Id = Params.get("id").and_then(|V| V.as_str()).unwrap_or("").to_string();
458
459 let Text = Params.get("text").and_then(|V| V.as_str()).unwrap_or("").to_string();
460
461 let Tooltip = Params.get("tooltip").and_then(|V| V.as_str()).unwrap_or("").to_string();
462
463 let _ = Service.environment.ApplicationHandle.emit(
470 "sky://statusbar/set-entry",
471 json!({ "id": Id, "text": Text, "tooltip": Tooltip }),
472 );
473
474 Ok(OkResponse(RequestId, &json!({ "itemId": Id })))
475 },
476
477 "setStatusBarText" => {
478 use tauri::Emitter;
479
480 let ItemId = Params.get("itemId").and_then(|V| V.as_str()).unwrap_or("").to_string();
481
482 let Text = Params.get("text").and_then(|V| V.as_str()).unwrap_or("").to_string();
483
484 let _ = Service
485 .environment
486 .ApplicationHandle
487 .emit("sky://statusbar/update", json!({ "id": ItemId, "text": Text }));
488
489 Ok(OkResponse(RequestId, &json!({ "success": true })))
490 },
491
492 "createWebviewPanel" => {
493 use tauri::Emitter;
494
495 let ViewType = Params.get("viewType").and_then(|V| V.as_str()).unwrap_or("").to_string();
496
497 let Title = Params.get("title").and_then(|V| V.as_str()).unwrap_or("").to_string();
498
499 let Handle = std::time::SystemTime::now()
500 .duration_since(std::time::UNIX_EPOCH)
501 .map(|D| D.as_millis() as u64)
502 .unwrap_or(0);
503
504 let _ = Service.environment.ApplicationHandle.emit("sky://webview/create", json!({ "handle": Handle, "viewType": ViewType, "title": Title, "viewColumn": Params.get("viewColumn"), "preserveFocus": Params.get("preserveFocus").and_then(|V| V.as_bool()).unwrap_or(false) }));
505
506 Ok(OkResponse(RequestId, &json!({ "handle": Handle })))
507 },
508
509 "setWebviewHtml" => {
510 use tauri::Emitter;
511
512 let Handle = Params.get("handle").and_then(|V| V.as_u64()).unwrap_or(0);
513
514 let Html = Params.get("html").and_then(|V| V.as_str()).unwrap_or("").to_string();
515
516 let _ = Service
518 .environment
519 .ApplicationHandle
520 .emit("sky://webview/set-html", json!({ "handle": Handle, "html": Html }));
521
522 Ok(OkResponse(RequestId, &json!({ "success": true })))
523 },
524
525 "findFiles" => {
537 use CommonLibrary::Workspace::WorkspaceProvider::WorkspaceProvider;
538
539 let Include = Params
540 .get("pattern")
541 .cloned()
542 .or_else(|| Params.get("include").cloned())
543 .unwrap_or(serde_json::Value::String("**".into()));
544
545 let Exclude = Params.get("exclude").cloned().filter(|V| !V.is_null());
546
547 let MaxResults = Params.get("maxResults").and_then(|V| V.as_u64()).map(|N| N as usize);
548
549 let UseIgnoreFiles = Params.get("useIgnoreFiles").and_then(|V| V.as_bool()).unwrap_or(true);
550
551 let FollowSymlinks = Params.get("followSymlinks").and_then(|V| V.as_bool()).unwrap_or(false);
552
553 match Service
554 .environment
555 .FindFilesInWorkspace(Include, Exclude, MaxResults, UseIgnoreFiles, FollowSymlinks)
556 .await
557 {
558 Ok(Urls) => {
559 Ok(OkResponse(
560 RequestId,
561 &json!({ "uris": Urls.into_iter().map(|U| U.to_string()).collect::<Vec<_>>() }),
562 ))
563 },
564
565 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("findFiles: {}", Error))),
566 }
567 },
568
569 "findTextInFiles" => {
570 use CommonLibrary::Search::SearchProvider::SearchProvider;
571
572 let QueryValue = if Params.get("pattern").map(|V| V.is_object()).unwrap_or(false) {
576 Params.get("pattern").cloned().unwrap_or(serde_json::Value::Null)
577 } else if Params.get("pattern").map(|V| V.is_string()).unwrap_or(false) {
578 json!({
579 "pattern": Params.get("pattern").and_then(|V| V.as_str()).unwrap_or(""),
580 "isRegExp": Params.get("isRegExp").and_then(|V| V.as_bool()).unwrap_or(false),
581 "isCaseSensitive": Params.get("isCaseSensitive").and_then(|V| V.as_bool()).unwrap_or(false),
582 "isWordMatch": Params.get("isWordMatch").and_then(|V| V.as_bool()).unwrap_or(false),
583 })
584 } else {
585 Params.clone()
586 };
587
588 let OptionsValue = Params.get("options").cloned().unwrap_or(serde_json::Value::Null);
589
590 match Service.environment.TextSearch(QueryValue, OptionsValue).await {
591 Ok(Matches) => Ok(OkResponse(RequestId, &json!({ "matches": Matches }))),
592
593 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("findTextInFiles: {}", Error))),
594 }
595 },
596
597 "openDocument" => {
598 use tauri::Emitter;
599
600 let Uri = Params
601 .get("uri")
602 .and_then(|V| V.get("value").or(Some(V)))
603 .and_then(|V| V.as_str())
604 .unwrap_or("")
605 .to_string();
606
607 let ViewColumn = Params.get("viewColumn").and_then(|V| V.as_i64());
608
609 let _ = Service
610 .environment
611 .ApplicationHandle
612 .emit("sky://editor/openDocument", json!({ "uri": Uri, "viewColumn": ViewColumn }));
613
614 Ok(OkResponse(RequestId, &json!({ "success": true })))
615 },
616
617 "saveAll" => {
618 use tauri::Emitter;
619
620 let IncludeUntitled = Params.get("includeUntitled").and_then(|V| V.as_bool()).unwrap_or(false);
621
622 let _ = Service
623 .environment
624 .ApplicationHandle
625 .emit("sky://editor/saveAll", json!({ "includeUntitled": IncludeUntitled }));
626
627 Ok(OkResponse(RequestId, &json!({ "success": true })))
628 },
629
630 "applyEdit" => {
631 use tauri::Emitter;
632
633 let Uri = Params
634 .get("uri")
635 .and_then(|V| V.get("value").or(Some(V)))
636 .and_then(|V| V.as_str())
637 .unwrap_or("")
638 .to_string();
639
640 let Edits = Params.get("edits").cloned().unwrap_or(json!([]));
641
642 let _ = Service
643 .environment
644 .ApplicationHandle
645 .emit("sky://editor/applyEdits", json!({ "uri": Uri, "edits": Edits }));
646
647 Ok(OkResponse(RequestId, &json!({ "success": true })))
648 },
649
650 "getSecret" => {
652 use CommonLibrary::Secret::SecretProvider::SecretProvider;
653
654 let ExtensionId = Params.get("extensionId").and_then(|V| V.as_str()).unwrap_or("").to_string();
655
656 let Key = Params.get("key").and_then(|V| V.as_str()).unwrap_or("").to_string();
657
658 match Service.environment.GetSecret(ExtensionId, Key).await {
659 Ok(Some(Value)) => Ok(OkResponse(RequestId, &json!({ "value": Value }))),
660
661 Ok(None) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
662
663 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
664 }
665 },
666
667 "storeSecret" => {
668 use CommonLibrary::Secret::SecretProvider::SecretProvider;
669
670 let ExtensionId = Params.get("extensionId").and_then(|V| V.as_str()).unwrap_or("").to_string();
671
672 let Key = Params.get("key").and_then(|V| V.as_str()).unwrap_or("").to_string();
673
674 let Value = Params.get("value").and_then(|V| V.as_str()).unwrap_or("").to_string();
675
676 match Service.environment.StoreSecret(ExtensionId, Key, Value).await {
677 Ok(()) => Ok(OkResponse(RequestId, &json!({ "success": true }))),
678
679 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
680 }
681 },
682
683 "deleteSecret" => {
684 use CommonLibrary::Secret::SecretProvider::SecretProvider;
685
686 let ExtensionId = Params.get("extensionId").and_then(|V| V.as_str()).unwrap_or("").to_string();
687
688 let Key = Params.get("key").and_then(|V| V.as_str()).unwrap_or("").to_string();
689
690 match Service.environment.DeleteSecret(ExtensionId, Key).await {
691 Ok(()) => Ok(OkResponse(RequestId, &json!({ "success": true }))),
692
693 Err(Error) => Ok(ErrResponse(RequestId, -32000, Error.to_string())),
694 }
695 },
696
697 "readFile" => {
699 let Uri = Params
700 .get("uri")
701 .and_then(|V| V.as_str())
702 .or_else(|| Params.as_str())
703 .unwrap_or("")
704 .replace("file://", "");
705
706 match tokio::fs::read(&Uri).await {
707 Ok(Content) => Ok(OkResponse(RequestId, &Content)),
708
709 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("readFile: {}", Error))),
710 }
711 },
712
713 "writeFile" => {
714 let Uri = Params.get("uri").and_then(|V| V.as_str()).unwrap_or("").replace("file://", "");
715
716 let Content:Vec<u8> = Params
717 .get("content")
718 .and_then(|V| V.as_array())
719 .map(|A| A.iter().filter_map(|B| B.as_u64().map(|N| N as u8)).collect())
720 .unwrap_or_default();
721
722 match tokio::fs::write(&Uri, &Content).await {
723 Ok(()) => Ok(OkResponse(RequestId, &serde_json::Value::Null)),
724
725 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("writeFile: {}", Error))),
726 }
727 },
728
729 "stat" => {
730 let Uri = Params
731 .get("uri")
732 .and_then(|V| V.as_str())
733 .or_else(|| Params.as_str())
734 .unwrap_or("")
735 .replace("file://", "");
736
737 match tokio::fs::metadata(&Uri).await {
738 Ok(Meta) => {
739 let Mtime = Meta
740 .modified()
741 .ok()
742 .and_then(|T| T.duration_since(UNIX_EPOCH).ok())
743 .map(|D| D.as_millis() as u64)
744 .unwrap_or(0);
745
746 Ok(OkResponse(
747 RequestId,
748 &json!({ "type": if Meta.is_dir() { 2 } else { 1 }, "is_file": Meta.is_file(), "is_directory": Meta.is_dir(), "size": Meta.len(), "mtime": Mtime }),
749 ))
750 },
751
752 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("stat: {}", Error))),
753 }
754 },
755
756 "readdir" => {
757 let Uri = Params
758 .get("uri")
759 .and_then(|V| V.as_str())
760 .or_else(|| Params.as_str())
761 .unwrap_or("")
762 .replace("file://", "");
763
764 match tokio::fs::read_dir(&Uri).await {
765 Ok(mut Entries) => {
766 let mut Names:Vec<String> = Vec::new();
767
768 while let Ok(Some(Entry)) = Entries.next_entry().await {
769 if let Some(Name) = Entry.file_name().to_str() {
770 Names.push(Name.to_string());
771 }
772 }
773
774 Ok(OkResponse(RequestId, &Names))
775 },
776
777 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("readdir: {}", Error))),
778 }
779 },
780
781 "$provideCallHierarchyItems" | "prepareCallHierarchy" => {
788 let URI_Raw = Params.get("uri").and_then(|V| V.as_str()).unwrap_or("");
789
790 let Line = Params
791 .get("position")
792 .and_then(|P| P.get("line"))
793 .and_then(|V| V.as_u64())
794 .unwrap_or(0);
795
796 let Char = Params
797 .get("position")
798 .and_then(|P| P.get("character"))
799 .and_then(|V| V.as_u64())
800 .unwrap_or(0);
801
802 match Url::parse(URI_Raw) {
803 Ok(DocURI) => {
804 let Pos = PositionDTO { LineNumber:Line as u32, Column:Char as u32 };
805
806 match Service.environment.PrepareCallHierarchy(DocURI, Pos).await {
807 Ok(Result) => Ok(OkResponse(RequestId, &Result)),
808
809 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("prepareCallHierarchy: {}", Error))),
810 }
811 },
812
813 Err(_) => Ok(OkResponse(RequestId, &serde_json::Value::Array(Vec::new()))),
814 }
815 },
816
817 "$provideTypeHierarchyItems" | "prepareTypeHierarchy" => {
818 let URI_Raw = Params.get("uri").and_then(|V| V.as_str()).unwrap_or("");
819
820 let Line = Params
821 .get("position")
822 .and_then(|P| P.get("line"))
823 .and_then(|V| V.as_u64())
824 .unwrap_or(0);
825
826 let Char = Params
827 .get("position")
828 .and_then(|P| P.get("character"))
829 .and_then(|V| V.as_u64())
830 .unwrap_or(0);
831
832 match Url::parse(URI_Raw) {
833 Ok(DocURI) => {
834 let Pos = PositionDTO { LineNumber:Line as u32, Column:Char as u32 };
835
836 match Service.environment.PrepareTypeHierarchy(DocURI, Pos).await {
837 Ok(Result) => Ok(OkResponse(RequestId, &Result)),
838
839 Err(Error) => Ok(ErrResponse(RequestId, -32000, format!("prepareTypeHierarchy: {}", Error))),
840 }
841 },
842
843 Err(_) => Ok(OkResponse(RequestId, &serde_json::Value::Array(Vec::new()))),
844 }
845 },
846
847 _ => {
849 dev_log!("cocoon", "warn: [CocoonService] Unknown generic method: {}", Req.method);
850
851 Ok(ErrResponse(RequestId, -32601, format!("Method '{}' not found", Req.method)))
852 },
853 }
854}