1#![allow(non_snake_case, non_camel_case_types)]
15
16use std::{future::Future, pin::Pin, sync::Arc};
17
18use Common::{
19 self,
20 Command::{ExecuteCommand::ExecuteCommand, GetAllCommands::GetAllCommands, RegisterCommand::RegisterCommand},
21 Configuration::{
22 ConfigurationInspector::ConfigurationInspector,
23 ConfigurationProvider::ConfigurationProvider,
24 DTO::ConfigurationTarget::ConfigurationTarget,
25 GetConfiguration::GetConfiguration,
26 },
27 CustomEditor::CustomEditorProvider::CustomEditorProvider,
28 Debug::DebugService::DebugService,
29 Diagnostic::DiagnosticManager::DiagnosticManager,
30 Document::{SaveDocument::SaveDocument, SaveDocumentAs::SaveDocumentAs},
31 Effect::{ActionEffect::ActionEffect, ApplicationRunTime::ApplicationRunTime as ApplicationRunTimeTrait},
32 Environment::Requires::Requires,
33 Error::CommonError::CommonError,
34 FileSystem::{
35 Delete::Delete,
36 ReadDirectory::ReadDirectory,
37 ReadFile::ReadFile,
38 StatFile::StatFile,
39 WriteFileBytes::WriteFileBytes,
40 },
41 Keybinding::KeybindingProvider::KeybindingProvider,
42 LanguageFeature::{
43 DTO::ProviderType::ProviderType,
44 LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
45 },
46 Search::SearchProvider::SearchProvider,
47 SourceControlManagement::SourceControlManagementProvider::SourceControlManagementProvider,
48 StatusBar::{DTO::StatusBarEntryDTO::StatusBarEntryDTO, StatusBarProvider::StatusBarProvider},
49 Storage::{GetStorageItem::GetStorageItem, SetStorageItem::SetStorageItem, StorageProvider::StorageProvider},
50 Terminal::TerminalProvider::TerminalProvider,
51 TreeView::TreeViewProvider::TreeViewProvider,
52 UserInterface::{ShowMessage::ShowMessage, ShowOpenDialog::ShowOpenDialog, ShowSaveDialog::ShowSaveDialog},
53 WebView::WebViewProvider::WebViewProvider,
54};
55use serde_json::{Value, from_value, json};
56use tauri::{AppHandle, Runtime};
57use url::Url;
58
59use crate::{
60 Environment::MountainEnvironment::MountainEnvironment,
61 RunTime::ApplicationRunTime::ApplicationRunTime as MountainRunTime,
62};
63
64pub type MappedEffect =
67 Box<dyn FnOnce(Arc<MountainRunTime>) -> Pin<Box<dyn Future<Output = Result<Value, String>> + Send>> + Send>;
68
69macro_rules! Parameter {
72 ($Parameter:expr, $Current:expr, $Type:ty) => {
73 from_value::<$Type>(
74 $Parameter
75 .get($Current)
76 .cloned()
77 .ok_or_else(|| format!("Missing parameter at index {}", $Current))?,
78 )
79 .map_err(|Error| format!("Invalid parameter at index {}: {}", $Current, Error))
80 };
81}
82
83fn Map<C, O, E>(Effect:ActionEffect<Arc<C>, E, O>) -> MappedEffect
87where
88 C: ?Sized + Send + Sync + 'static,
89 O: serde::Serialize + Send + Sync + 'static,
90 E: Into<CommonError> + From<CommonError> + Send + Sync + 'static,
91 MountainEnvironment: Requires<C>, {
92 Box::new(move |RunTime:Arc<MountainRunTime>| {
93 Box::pin(async move {
94 let Result = RunTime.Run(Effect).await;
95
96 match Result {
97 Ok(Output) => serde_json::to_value(Output).map_err(|Error| format!("Serialization failed: {}", Error)),
98
99 Err(Error) => {
100 let CommonError:CommonError = Error.into();
101
102 Err(CommonError.to_string())
103 },
104 }
105 })
106 })
107}
108
109pub fn CreateEffectForRequest<R:Runtime>(
113 _ApplicationHandle:&AppHandle<R>,
114
115 Method:&str,
116
117 Parameters:Value,
118) -> Result<MappedEffect, String> {
119 let ParametersArray = Parameters
120 .as_array()
121 .ok_or_else(|| format!("Parameters for '{}' must be an array.", Method))?;
122
123 match Method {
126 "Configuration.Inspect" => {
128 let Key = Parameter!(ParametersArray, 0, String)?;
129
130 let Overrides = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
131
132 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
133 Box::pin(async move {
134 let provider:Arc<dyn ConfigurationInspector> = runtime.Environment.Require();
135
136 let result = provider
137 .InspectConfigurationValue(Key, from_value(Overrides).unwrap_or_default())
138 .await
139 .map_err(|Error| Error.to_string())?;
140
141 Ok(serde_json::to_value(result).unwrap_or(Value::Null))
142 })
143 }));
144 },
145
146 "Configuration.Update" => {
147 let Key = Parameter!(ParametersArray, 0, String)?;
148
149 let ValueToSet = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
150
151 let Target = Parameter!(ParametersArray, 2, ConfigurationTarget)?;
152
153 let Overrides = ParametersArray.get(3).cloned().unwrap_or(Value::Null);
154
155 let ScopeToLang = Parameter!(ParametersArray, 4, Option<bool>)?;
156
157 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
158 Box::pin(async move {
159 let provider:Arc<dyn ConfigurationProvider> = runtime.Environment.Require();
160
161 provider
162 .UpdateConfigurationValue(
163 Key,
164 ValueToSet,
165 Target,
166 from_value(Overrides).unwrap_or_default(),
167 ScopeToLang,
168 )
169 .await
170 .map_err(|Error| Error.to_string())?;
171
172 Ok(Value::Null)
173 })
174 }));
175 },
176
177 "$resolveCustomEditor" => {
179 let ViewType = Parameter!(ParametersArray, 0, String)?;
180
181 let ResourceURI = Parameter!(ParametersArray, 1, Url)?;
182
183 let WebViewPanelHandle = Parameter!(ParametersArray, 2, String)?;
184
185 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
186 Box::pin(async move {
187 let provider:Arc<dyn CustomEditorProvider> = runtime.Environment.Require();
188
189 provider
190 .ResolveCustomEditor(ViewType, ResourceURI, WebViewPanelHandle)
191 .await
192 .map_err(|Error| Error.to_string())?;
193
194 Ok(Value::Null)
195 })
196 }));
197 },
198
199 "Debug.Start" => {
201 let folder_uri_val = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
202
203 let config = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
204
205 let folder_uri = if folder_uri_val.is_null() {
206 None
207 } else {
208 Some(from_value(folder_uri_val).map_err(|Error| Error.to_string())?)
209 };
210
211 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
212 Box::pin(async move {
213 let provider:Arc<dyn DebugService> = runtime.Environment.Require();
214
215 let session_id = provider
216 .StartDebugging(folder_uri, config)
217 .await
218 .map_err(|Error| Error.to_string())?;
219
220 Ok(json!(session_id))
221 })
222 }));
223 },
224
225 "Debug.RegisterConfigurationProvider" => {
226 let dbg_type = Parameter!(ParametersArray, 0, String)?;
227
228 let handle = Parameter!(ParametersArray, 1, u32)?;
229
230 let sidecar_id = Parameter!(ParametersArray, 2, String)?;
231
232 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
233 Box::pin(async move {
234 let provider:Arc<dyn DebugService> = runtime.Environment.Require();
235
236 provider
237 .RegisterDebugConfigurationProvider(dbg_type, handle, sidecar_id)
238 .await
239 .map_err(|Error| Error.to_string())?;
240
241 Ok(Value::Null)
242 })
243 }));
244 },
245
246 "Diagnostic.Set" => {
248 let Owner = Parameter!(ParametersArray, 0, String)?;
249
250 let Entries = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
251
252 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
253 Box::pin(async move {
254 let provider:Arc<dyn DiagnosticManager> = runtime.Environment.Require();
255
256 provider
257 .SetDiagnostics(Owner, Entries)
258 .await
259 .map_err(|Error| Error.to_string())?;
260
261 Ok(Value::Null)
262 })
263 }));
264 },
265
266 "Diagnostic.Clear" => {
267 let Owner = Parameter!(ParametersArray, 0, String)?;
268
269 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
270 Box::pin(async move {
271 let provider:Arc<dyn DiagnosticManager> = runtime.Environment.Require();
272
273 provider.ClearDiagnostics(Owner).await.map_err(|Error| Error.to_string())?;
274
275 Ok(Value::Null)
276 })
277 }));
278 },
279
280 "Keybinding.GetResolved" => {
282 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
283 Box::pin(async move {
284 let provider:Arc<dyn KeybindingProvider> = runtime.Environment.Require();
285
286 provider.GetResolvedKeybinding().await.map_err(|Error| Error.to_string())
287 })
288 }));
289 },
290
291 "$languageFeatures:registerProvider" => {
293 let SideCarID = Parameter!(ParametersArray, 0, String)?;
294
295 let ProviderType = Parameter!(ParametersArray, 1, ProviderType)?;
296
297 let Selector = ParametersArray.get(2).cloned().unwrap_or(Value::Null);
298
299 let ExtensionID = ParametersArray.get(3).cloned().unwrap_or(Value::Null);
300
301 let Options = ParametersArray.get(4).cloned();
302
303 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
304 Box::pin(async move {
305 let provider:Arc<dyn LanguageFeatureProviderRegistry> = runtime.Environment.Require();
306
307 let handle = provider
308 .RegisterProvider(SideCarID, ProviderType, Selector, ExtensionID, Options)
309 .await
310 .map_err(|Error| Error.to_string())?;
311
312 Ok(json!(handle))
313 })
314 }));
315 },
316
317 "$languageFeatures:unregisterProvider" => {
318 let Handle = Parameter!(ParametersArray, 0, u32)?;
319
320 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
321 Box::pin(async move {
322 let provider:Arc<dyn LanguageFeatureProviderRegistry> = runtime.Environment.Require();
323
324 provider.UnregisterProvider(Handle).await.map_err(|Error| Error.to_string())?;
325
326 Ok(Value::Null)
327 })
328 }));
329 },
330
331 "Search.TextSearch" => {
333 let Query = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
334
335 let Options = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
336
337 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
338 Box::pin(async move {
339 let provider:Arc<dyn SearchProvider> = runtime.Environment.Require();
340
341 let result = provider.TextSearch(Query, Options).await.map_err(|Error| Error.to_string())?;
342
343 Ok(result)
344 })
345 }));
346 },
347
348 "$scm:createSourceControl" => {
350 let DTO = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
351
352 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
353 Box::pin(async move {
354 let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
355
356 let handle = provider.CreateSourceControl(DTO).await.map_err(|Error| Error.to_string())?;
357
358 Ok(json!(handle))
359 })
360 }));
361 },
362
363 "$scm:updateSourceControl" => {
364 let handle = Parameter!(ParametersArray, 0, u32)?;
365
366 let dto = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
367
368 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
369 Box::pin(async move {
370 let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
371
372 provider
373 .UpdateSourceControl(handle, dto)
374 .await
375 .map_err(|Error| Error.to_string())?;
376
377 Ok(Value::Null)
378 })
379 }));
380 },
381
382 "$scm:updateGroup" => {
383 let handle = Parameter!(ParametersArray, 0, u32)?;
384
385 let dto = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
386
387 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
388 Box::pin(async move {
389 let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
390
391 provider
392 .UpdateSourceControlGroup(handle, dto)
393 .await
394 .map_err(|Error| Error.to_string())?;
395
396 Ok(Value::Null)
397 })
398 }));
399 },
400
401 "$scm:registerInputBox" => {
402 let handle = Parameter!(ParametersArray, 0, u32)?;
403
404 let dto = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
405
406 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
407 Box::pin(async move {
408 let provider:Arc<dyn SourceControlManagementProvider> = runtime.Environment.Require();
409
410 provider
411 .RegisterInputBox(handle, dto)
412 .await
413 .map_err(|Error| Error.to_string())?;
414
415 Ok(Value::Null)
416 })
417 }));
418 },
419
420 "$statusBar:set" => {
422 let EntryDTO = Parameter!(ParametersArray, 0, StatusBarEntryDTO)?;
423
424 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
425 Box::pin(async move {
426 let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
427
428 provider.SetStatusBarEntry(EntryDTO).await.map_err(|Error| Error.to_string())?;
429
430 Ok(Value::Null)
431 })
432 }));
433 },
434
435 "$statusBar:dispose" => {
436 let EntryID = Parameter!(ParametersArray, 0, String)?;
437
438 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
439 Box::pin(async move {
440 let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
441
442 provider
443 .DisposeStatusBarEntry(EntryID)
444 .await
445 .map_err(|Error| Error.to_string())?;
446
447 Ok(Value::Null)
448 })
449 }));
450 },
451
452 "$setStatusBarMessage" => {
453 let ID = Parameter!(ParametersArray, 0, String)?;
454
455 let Text = Parameter!(ParametersArray, 1, String)?;
456
457 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
458 Box::pin(async move {
459 let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
460
461 provider
462 .SetStatusBarMessage(ID, Text)
463 .await
464 .map_err(|Error| Error.to_string())?;
465
466 Ok(Value::Null)
467 })
468 }));
469 },
470
471 "$disposeStatusBarMessage" => {
472 let ID = Parameter!(ParametersArray, 0, String)?;
473
474 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
475 Box::pin(async move {
476 let provider:Arc<dyn StatusBarProvider> = runtime.Environment.Require();
477
478 provider.DisposeStatusBarMessage(ID).await.map_err(|Error| Error.to_string())?;
479
480 Ok(Value::Null)
481 })
482 }));
483 },
484
485 "$storage:getAll" => {
487 let IsGlobal = Parameter!(ParametersArray, 0, bool)?;
488
489 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
490 Box::pin(async move {
491 let provider:Arc<dyn StorageProvider> = runtime.Environment.Require();
492
493 provider.GetAllStorage(IsGlobal).await.map_err(|Error| Error.to_string())
494 })
495 }));
496 },
497
498 "$storage:setAll" => {
499 let IsGlobal = Parameter!(ParametersArray, 0, bool)?;
500
501 let State = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
502
503 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
504 Box::pin(async move {
505 let provider:Arc<dyn StorageProvider> = runtime.Environment.Require();
506
507 provider
508 .SetAllStorage(IsGlobal, State)
509 .await
510 .map_err(|Error| Error.to_string())?;
511
512 Ok(Value::Null)
513 })
514 }));
515 },
516
517 "$terminal:create" => {
519 let OptionsValue = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
520
521 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
522 Box::pin(async move {
523 let provider:Arc<dyn TerminalProvider> = runtime.Environment.Require();
524
525 let result = provider.CreateTerminal(OptionsValue).await.map_err(|Error| Error.to_string())?;
526
527 Ok(result)
528 })
529 }));
530 },
531
532 "$terminal:sendText" => {
533 let TerminalId = Parameter!(ParametersArray, 0, u64)?;
534
535 let Text = Parameter!(ParametersArray, 1, String)?;
536
537 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
538 Box::pin(async move {
539 let provider:Arc<dyn TerminalProvider> = runtime.Environment.Require();
540
541 provider
542 .SendTextToTerminal(TerminalId, Text)
543 .await
544 .map_err(|Error| Error.to_string())?;
545
546 Ok(Value::Null)
547 })
548 }));
549 },
550
551 "$terminal:dispose" => {
552 let TerminalId = Parameter!(ParametersArray, 0, u64)?;
553
554 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
555 Box::pin(async move {
556 let provider:Arc<dyn TerminalProvider> = runtime.Environment.Require();
557
558 provider.DisposeTerminal(TerminalId).await.map_err(|Error| Error.to_string())?;
559
560 Ok(Value::Null)
561 })
562 }));
563 },
564
565 "$tree:register" => {
567 let ID = Parameter!(ParametersArray, 0, String)?;
568
569 let Options = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
570
571 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
572 Box::pin(async move {
573 let provider:Arc<dyn TreeViewProvider> = runtime.Environment.Require();
574
575 provider
576 .RegisterTreeDataProvider(ID, Options)
577 .await
578 .map_err(|Error| Error.to_string())?;
579
580 Ok(Value::Null)
581 })
582 }));
583 },
584
585 "$webview:create" => {
587 let ExtData = Parameter!(ParametersArray, 0, Value)?;
588
589 let ViewType = Parameter!(ParametersArray, 1, String)?;
590
591 let Title = Parameter!(ParametersArray, 2, String)?;
592
593 let ShowOpts = Parameter!(ParametersArray, 3, Value)?;
594
595 let PanelOpts = Parameter!(ParametersArray, 4, Value)?;
596
597 let ContentOpts = Parameter!(ParametersArray, 5, Value)?;
598
599 return Ok(Box::new(move |runtime:Arc<MountainRunTime>| {
600 Box::pin(async move {
601 let provider:Arc<dyn WebViewProvider> = runtime.Environment.Require();
602
603 let handle = provider
604 .CreateWebViewPanel(ExtData, ViewType, Title, ShowOpts, PanelOpts, ContentOpts)
605 .await
606 .map_err(|Error| Error.to_string())?;
607
608 Ok(json!(handle))
609 })
610 }));
611 },
612
613 _ => {},
615 }
616
617 let effect = match Method {
619 "Command.Execute" => {
621 let ID = Parameter!(ParametersArray, 0, String)?;
622
623 let Args = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
624
625 Map(ExecuteCommand(ID, Args))
626 },
627
628 "Command.GetAll" => Map(GetAllCommands()),
629
630 "Command.Register" => {
631 let SideCarID = Parameter!(ParametersArray, 0, String)?;
632
633 let CommandID = Parameter!(ParametersArray, 1, String)?;
634
635 Map(RegisterCommand(SideCarID, CommandID))
636 },
637
638 "Configuration.Get" => {
640 let Section = Parameter!(ParametersArray, 0, Option<String>)?;
641
642 let Overrides = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
643
644 Map(GetConfiguration(Section, Overrides))
645 },
646
647 "Document.Save" => {
649 let uri_str = Parameter!(ParametersArray, 0, String)?;
650
651 let uri = Url::parse(&uri_str).map_err(|Error| format!("Invalid URI parameter: {}", Error))?;
652
653 Map(SaveDocument(uri))
654 },
655
656 "Document.SaveAs" => {
657 let original_uri_str = Parameter!(ParametersArray, 0, String)?;
658
659 let original_uri =
660 Url::parse(&original_uri_str).map_err(|Error| format!("Invalid URI parameter: {}", Error))?;
661
662 Map(SaveDocumentAs(original_uri, None))
663 },
664
665 "FileSystem.ReadFile" => {
667 let Path = Parameter!(ParametersArray, 0, _)?;
668
669 Map(ReadFile(Path))
670 },
671
672 "FileSystem.StatFile" => {
673 let Path = Parameter!(ParametersArray, 0, _)?;
674
675 Map(StatFile(Path))
676 },
677
678 "FileSystem.ReadDirectory" => {
679 let Path = Parameter!(ParametersArray, 0, _)?;
680
681 Map(ReadDirectory(Path))
682 },
683
684 "FileSystem.WriteFile" => {
685 let Path = Parameter!(ParametersArray, 0, _)?;
686
687 let Content = Parameter!(ParametersArray, 1, Vec<u8>)?;
688
689 let Create = Parameter!(ParametersArray, 2, bool)?;
690
691 let Overwrite = Parameter!(ParametersArray, 3, bool)?;
692
693 Map(WriteFileBytes(Path, Content, Create, Overwrite))
694 },
695
696 "FileSystem.Delete" => {
697 let Path = Parameter!(ParametersArray, 0, _)?;
698
699 let Recursive = Parameter!(ParametersArray, 1, bool)?;
700
701 let UseTrash = Parameter!(ParametersArray, 2, bool)?;
702
703 Map(Delete(Path, Recursive, UseTrash))
704 },
705
706 "Storage.Get" => {
708 let TargetObject = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
709
710 Map(GetStorageItem(TargetObject))
711 },
712
713 "Storage.Set" => {
714 let TargetObject = ParametersArray.get(0).cloned().unwrap_or(Value::Null);
715
716 let ValueToSet = ParametersArray.get(1).cloned().unwrap_or(Value::Null);
717
718 Map(SetStorageItem(TargetObject, ValueToSet))
719 },
720
721 "UserInterface.ShowMessage" => {
723 let Severity = Parameter!(ParametersArray, 0, _)?;
724
725 let Message = Parameter!(ParametersArray, 1, String)?;
726
727 let Options = ParametersArray.get(2).cloned().unwrap_or(Value::Null);
728
729 Map(ShowMessage(Severity, Message, Options))
730 },
731
732 "UserInterface.ShowOpenDialog" => {
733 let Options = Parameter!(ParametersArray, 0, _)?;
734
735 Map(ShowOpenDialog(Options))
736 },
737
738 "UserInterface.ShowSaveDialog" => {
739 let Options = Parameter!(ParametersArray, 0, _)?;
740
741 Map(ShowSaveDialog(Options))
742 },
743
744 _ => return Err(format!("No mapping found for method: {}", Method)),
745 };
746
747 Ok(effect)
748}