1use std::sync::{
8 Arc,
9 Mutex,
10 atomic::{AtomicU32, Ordering},
11};
12
13use serde::{Deserialize, Serialize};
14
15use crate::{API::Types::*, Transport::Strategy::Transport, dev_log};
16
17#[derive(Debug, Default)]
26struct ProviderStore {
27 entries:Mutex<std::collections::HashMap<u32, (String, String)>>,
29 next_handle:AtomicU32,
31}
32
33impl ProviderStore {
34 fn insert(&self, provider_type:&str, selector:&str) -> u32 {
36 let Handle = self.next_handle.fetch_add(1, Ordering::Relaxed);
37 if let Ok(mut Guard) = self.entries.lock() {
38 Guard.insert(Handle, (provider_type.to_string(), selector.to_string()));
39 }
40 Handle
41 }
42
43 fn remove(&self, handle:u32) {
45 if let Ok(mut Guard) = self.entries.lock() {
46 Guard.remove(&handle);
47 }
48 }
49
50 #[allow(dead_code)]
52 fn len(&self) -> usize { self.entries.lock().map(|G| G.len()).unwrap_or(0) }
53}
54
55#[derive(Debug, Clone)]
57pub struct VSCodeAPI {
58 pub commands:Arc<CommandNamespace>,
60 pub window:Arc<Window>,
62 pub workspace:Arc<Workspace>,
64 pub languages:Arc<LanguageNamespace>,
66 pub extensions:Arc<ExtensionNamespace>,
68 pub env:Arc<Env>,
70}
71
72impl VSCodeAPI {
73 pub fn new() -> Self {
76 Self {
77 commands:Arc::new(CommandNamespace::new()),
78 window:Arc::new(Window::new()),
79 workspace:Arc::new(Workspace::new()),
80 languages:Arc::new(LanguageNamespace::new()),
81 extensions:Arc::new(ExtensionNamespace::new()),
82 env:Arc::new(Env::new()),
83 }
84 }
85
86 pub fn new_with_transport(transport:Arc<Transport>) -> Self {
90 Self {
91 commands:Arc::new(CommandNamespace::new()),
92 window:Arc::new(Window::new()),
93 workspace:Arc::new(Workspace::new()),
94 languages:Arc::new(LanguageNamespace::new_with_transport(Arc::clone(&transport))),
95 extensions:Arc::new(ExtensionNamespace::new()),
96 env:Arc::new(Env::new()),
97 }
98 }
99}
100
101impl Default for VSCodeAPI {
102 fn default() -> Self { Self::new() }
103}
104
105#[derive(Debug, Clone)]
107pub struct CommandNamespace;
108
109impl CommandNamespace {
110 pub fn new() -> Self { Self }
112
113 pub fn register_command(&self, command_id:String, _callback:CommandCallback) -> Result<Command, String> {
115 Ok(Command { id:command_id.clone() })
116 }
117
118 pub async fn execute_command<T:serde::de::DeserializeOwned>(
120 &self,
121 command_id:String,
122 _args:Vec<serde_json::Value>,
123 ) -> Result<T, String> {
124 Err(format!("Command not implemented: {}", command_id))
126 }
127}
128
129pub type CommandCallback = Box<dyn Fn(Vec<serde_json::Value>) -> Result<serde_json::Value, String> + Send + Sync>;
131
132#[derive(Debug, Clone)]
134pub struct Command {
135 pub id:String,
137}
138
139#[derive(Debug, Clone)]
141pub struct Window;
142
143impl Window {
144 pub fn new() -> Self { Self }
146
147 pub async fn show_information_message(&self, _message:String) -> Result<String, String> {
149 Ok("OK".to_string())
151 }
152
153 pub async fn show_warning_message(&self, _message:String) -> Result<String, String> {
155 Ok("OK".to_string())
157 }
158
159 pub async fn show_error_message(&self, _message:String) -> Result<String, String> {
161 Ok("OK".to_string())
163 }
164
165 pub fn create_output_channel(&self, name:String) -> OutputChannel { OutputChannel::new(name) }
167}
168
169#[derive(Debug, Clone)]
171pub struct OutputChannel {
172 name:String,
174}
175
176impl OutputChannel {
177 pub fn new(name:String) -> Self { Self { name } }
183
184 pub fn append_line(&self, line:&str) {
186 dev_log!("output", "[{}] {}", self.name, line);
187 }
188
189 pub fn append(&self, value:&str) {
191 dev_log!("output", "[{}] {}", self.name, value);
192 }
193
194 pub fn show(&self) {
196 }
198
199 pub fn hide(&self) {
201 }
203
204 pub fn dispose(&self) {
206 }
208}
209
210#[derive(Debug, Clone)]
212pub struct Workspace;
213
214impl Workspace {
215 pub fn new() -> Self { Self }
217
218 pub fn workspace_folders(&self) -> Vec<WorkspaceFolder> {
220 Vec::new()
222 }
223
224 pub fn get_configuration(&self, section:Option<String>) -> WorkspaceConfiguration {
226 WorkspaceConfiguration::new(section)
227 }
228}
229
230#[derive(Debug, Clone, Serialize, Deserialize)]
232pub struct WorkspaceFolder {
233 pub uri:String,
235
236 pub name:String,
238
239 pub index:u32,
241}
242
243#[derive(Debug, Clone)]
245pub struct WorkspaceConfiguration {
246 #[allow(dead_code)]
248 section:Option<String>,
249}
250
251impl WorkspaceConfiguration {
252 pub fn new(section:Option<String>) -> Self { Self { section } }
258
259 pub fn get<T:serde::de::DeserializeOwned>(&self, _key:String) -> Result<T, String> {
261 Err("Configuration not implemented".to_string())
263 }
264
265 pub fn has(&self, _key:String) -> bool { false }
267
268 pub async fn update(&self, _key:String, _value:serde_json::Value) -> Result<(), String> {
270 Err("Update configuration not implemented".to_string())
272 }
273}
274
275#[derive(Debug)]
285pub struct LanguageNamespace {
286 store:Arc<ProviderStore>,
288 transport:Option<Arc<Transport>>,
290}
291
292impl Clone for LanguageNamespace {
293 fn clone(&self) -> Self { Self { store:Arc::clone(&self.store), transport:self.transport.clone() } }
294}
295
296impl LanguageNamespace {
297 pub fn new() -> Self { Self { store:Arc::new(ProviderStore::default()), transport:None } }
299
300 pub fn new_with_transport(transport:Arc<Transport>) -> Self {
304 Self { store:Arc::new(ProviderStore::default()), transport:Some(transport) }
305 }
306
307 pub fn active_registration_count(&self) -> usize { self.store.len() }
309
310 fn register(&self, provider_type:&str, selector:&DocumentSelector) -> Disposable {
312 let ProviderTypeOwned = provider_type.to_string();
313 let SelectorStr = selector
314 .iter()
315 .filter_map(|F| F.language.as_deref())
316 .collect::<Vec<_>>()
317 .join(",");
318 let Handle = self.store.insert(&ProviderTypeOwned, &SelectorStr);
319 let Store = Arc::clone(&self.store);
320 dev_log!(
321 "extensions",
322 "[LanguageNamespace] registered {} handle={} selector={}",
323 ProviderTypeOwned,
324 Handle,
325 SelectorStr
326 );
327
328 if let Some(Transport) = &self.transport {
330 let Notification = serde_json::json!({
331 "method": format!("register_{}", ProviderTypeOwned),
332 "parameters": {
333 "handle": Handle,
334 "language_selector": SelectorStr,
335 "extension_id": "grove-extension",
336 }
337 });
338 if let Ok(Bytes) = serde_json::to_vec(&Notification) {
339 let TransportClone = Arc::clone(Transport);
340 tokio::spawn(async move {
341 let _ = TransportClone.send_no_response(&Bytes).await;
342 });
343 }
344 }
345
346 Disposable::with_callback(Box::new(move || {
347 Store.remove(Handle);
348 dev_log!(
349 "extensions",
350 "[LanguageNamespace] disposed {} handle={}",
351 ProviderTypeOwned,
352 Handle
353 );
354 }))
355 }
356
357 pub async fn register_completion_item_provider<T:CompletionItemProvider>(
359 &self,
360 selector:DocumentSelector,
361 _provider:T,
362 _trigger_characters:Option<Vec<String>>,
363 ) -> Result<Disposable, String> {
364 Ok(self.register("completion", &selector))
365 }
366
367 pub fn register_hover_provider(&self, selector:DocumentSelector) -> Disposable { self.register("hover", &selector) }
369
370 pub fn register_definition_provider(&self, selector:DocumentSelector) -> Disposable {
372 self.register("definition", &selector)
373 }
374
375 pub fn register_reference_provider(&self, selector:DocumentSelector) -> Disposable {
377 self.register("references", &selector)
378 }
379
380 pub fn register_code_actions_provider(&self, selector:DocumentSelector) -> Disposable {
382 self.register("codeAction", &selector)
383 }
384
385 pub fn register_document_highlight_provider(&self, selector:DocumentSelector) -> Disposable {
387 self.register("documentHighlight", &selector)
388 }
389
390 pub fn register_document_symbol_provider(&self, selector:DocumentSelector) -> Disposable {
392 self.register("documentSymbol", &selector)
393 }
394
395 pub fn register_workspace_symbol_provider(&self) -> Disposable { self.register("workspaceSymbol", &Vec::new()) }
397
398 pub fn register_rename_provider(&self, selector:DocumentSelector) -> Disposable {
400 self.register("rename", &selector)
401 }
402
403 pub fn register_document_formatting_edit_provider(&self, selector:DocumentSelector) -> Disposable {
405 self.register("documentFormatting", &selector)
406 }
407
408 pub fn register_document_range_formatting_edit_provider(&self, selector:DocumentSelector) -> Disposable {
410 self.register("documentRangeFormatting", &selector)
411 }
412
413 pub fn register_on_type_formatting_edit_provider(
415 &self,
416 selector:DocumentSelector,
417 _trigger_characters:Vec<String>,
418 ) -> Disposable {
419 self.register("onTypeFormatting", &selector)
420 }
421
422 pub fn register_signature_help_provider(&self, selector:DocumentSelector) -> Disposable {
424 self.register("signatureHelp", &selector)
425 }
426
427 pub fn register_code_lens_provider(&self, selector:DocumentSelector) -> Disposable {
429 self.register("codeLens", &selector)
430 }
431
432 pub fn register_folding_range_provider(&self, selector:DocumentSelector) -> Disposable {
434 self.register("foldingRange", &selector)
435 }
436
437 pub fn register_selection_range_provider(&self, selector:DocumentSelector) -> Disposable {
439 self.register("selectionRange", &selector)
440 }
441
442 pub fn register_document_semantic_tokens_provider(&self, selector:DocumentSelector) -> Disposable {
444 self.register("semanticTokens", &selector)
445 }
446
447 pub fn register_inlay_hints_provider(&self, selector:DocumentSelector) -> Disposable {
449 self.register("inlayHints", &selector)
450 }
451
452 pub fn register_type_hierarchy_provider(&self, selector:DocumentSelector) -> Disposable {
454 self.register("typeHierarchy", &selector)
455 }
456
457 pub fn register_call_hierarchy_provider(&self, selector:DocumentSelector) -> Disposable {
459 self.register("callHierarchy", &selector)
460 }
461
462 pub fn register_linked_editing_range_provider(&self, selector:DocumentSelector) -> Disposable {
464 self.register("linkedEditingRange", &selector)
465 }
466
467 pub fn register_declaration_provider(&self, selector:DocumentSelector) -> Disposable {
469 self.register("declaration", &selector)
470 }
471
472 pub fn register_implementation_provider(&self, selector:DocumentSelector) -> Disposable {
474 self.register("implementation", &selector)
475 }
476
477 pub fn register_type_definition_provider(&self, selector:DocumentSelector) -> Disposable {
479 self.register("typeDefinition", &selector)
480 }
481
482 pub fn create_diagnostic_collection(&self, name:Option<String>) -> DiagnosticCollection {
484 DiagnosticCollection::new(name)
485 }
486
487 pub fn set_language_configuration(&self, language:String) -> Disposable {
489 self.register(
490 "languageConfiguration",
491 &vec![DocumentFilter { language:Some(language), scheme:None, pattern:None }],
492 )
493 }
494}
495
496#[derive(Debug, Clone, Serialize, Deserialize)]
498pub struct DocumentFilter {
499 pub language:Option<String>,
501
502 pub scheme:Option<String>,
504
505 pub pattern:Option<String>,
507}
508
509pub type DocumentSelector = Vec<DocumentFilter>;
511
512pub trait CompletionItemProvider: Send + Sync {
514 fn provide_completion_items(
527 &self,
528 document:TextDocumentIdentifier,
529 position:Position,
530 context:CompletionContext,
531 token:Option<String>,
532 ) -> Vec<CompletionItem>;
533}
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
537pub struct CompletionContext {
538 #[serde(rename = "triggerKind")]
540 pub trigger_kind:CompletionTriggerKind,
541
542 #[serde(rename = "triggerCharacter")]
544 pub trigger_character:Option<String>,
545}
546
547#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
549pub enum CompletionTriggerKind {
550 #[serde(rename = "Invoke")]
552 Invoke = 0,
553
554 #[serde(rename = "TriggerCharacter")]
556 TriggerCharacter = 1,
557
558 #[serde(rename = "TriggerForIncompleteCompletions")]
560 TriggerForIncompleteCompletions = 2,
561}
562
563#[derive(Debug, Clone)]
565pub struct DiagnosticCollection {
566 #[allow(dead_code)]
568 name:Option<String>,
569}
570
571impl DiagnosticCollection {
572 pub fn new(name:Option<String>) -> Self { Self { name } }
578
579 pub fn set(&self, _uri:String, _diagnostics:Vec<Diagnostic>) {
581 }
583
584 pub fn delete(&self, _uri:String) {
586 }
588
589 pub fn clear(&self) {
591 }
593
594 pub fn dispose(&self) {
596 }
598}
599
600pub struct Disposable {
605 callback:Option<Box<dyn FnOnce() + Send + Sync>>,
606}
607
608impl std::fmt::Debug for Disposable {
609 fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result {
610 f.debug_struct("Disposable")
611 .field("has_callback", &self.callback.is_some())
612 .finish()
613 }
614}
615
616impl Clone for Disposable {
617 fn clone(&self) -> Self { Self { callback:None } }
620}
621
622impl Disposable {
623 pub fn new() -> Self { Self { callback:None } }
625
626 pub fn with_callback(callback:Box<dyn FnOnce() + Send + Sync>) -> Self { Self { callback:Some(callback) } }
628
629 pub fn dispose(mut self) {
631 if let Some(Callback) = self.callback.take() {
632 Callback();
633 }
634 }
635}
636
637impl Default for Disposable {
638 fn default() -> Self { Self::new() }
639}
640
641#[derive(Debug, Clone)]
643pub struct ExtensionNamespace;
644
645impl ExtensionNamespace {
646 pub fn new() -> Self { Self }
648
649 pub fn all(&self) -> Vec<Extension> { Vec::new() }
651
652 pub fn get_extension(&self, _extension_id:String) -> Option<Extension> { None }
654}
655
656#[derive(Debug, Clone, Serialize, Deserialize)]
658pub struct Extension {
659 pub id:String,
661
662 #[serde(rename = "extensionPath")]
664 pub extension_path:String,
665
666 pub is_active:bool,
668
669 #[serde(rename = "packageJSON")]
671 pub package_json:serde_json::Value,
672}
673
674#[derive(Debug, Clone)]
676pub struct Env;
677
678impl Env {
679 pub fn new() -> Self { Self }
681
682 pub fn get_env_var(&self, name:String) -> Option<String> { std::env::var(name).ok() }
684
685 pub fn is_windows(&self) -> bool { cfg!(windows) }
687
688 pub fn is_mac(&self) -> bool { cfg!(target_os = "macos") }
690
691 pub fn is_linux(&self) -> bool { cfg!(target_os = "linux") }
693
694 pub fn app_name(&self) -> String { "VS Code".to_string() }
696
697 pub fn app_root(&self) -> Option<String> { std::env::var("VSCODE_APP_ROOT").ok() }
699}
700
701#[cfg(test)]
702mod tests {
703 use super::*;
704
705 #[test]
706 fn test_vscode_api_creation() {
707 let _api = VSCodeAPI::new();
708 }
710
711 #[test]
712 fn test_position_operations() {
713 let pos = Position::new(5, 10);
714 assert_eq!(pos.line, 5);
715 assert_eq!(pos.character, 10);
716 }
717
718 #[test]
719 fn test_output_channel() {
720 let channel = OutputChannel::new("test".to_string());
721 channel.append_line("test message");
722 }
723
724 #[test]
725 fn test_disposable() {
726 let disposable = Disposable::new();
727 disposable.dispose();
728 }
729}