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!("extensions", "[LanguageNamespace] disposed {} handle={}", ProviderTypeOwned, Handle);
349 }))
350 }
351
352 pub async fn register_completion_item_provider<T:CompletionItemProvider>(
354 &self,
355 selector:DocumentSelector,
356 _provider:T,
357 _trigger_characters:Option<Vec<String>>,
358 ) -> Result<Disposable, String> {
359 Ok(self.register("completion", &selector))
360 }
361
362 pub fn register_hover_provider(&self, selector:DocumentSelector) -> Disposable { self.register("hover", &selector) }
364
365 pub fn register_definition_provider(&self, selector:DocumentSelector) -> Disposable {
367 self.register("definition", &selector)
368 }
369
370 pub fn register_reference_provider(&self, selector:DocumentSelector) -> Disposable {
372 self.register("references", &selector)
373 }
374
375 pub fn register_code_actions_provider(&self, selector:DocumentSelector) -> Disposable {
377 self.register("codeAction", &selector)
378 }
379
380 pub fn register_document_highlight_provider(&self, selector:DocumentSelector) -> Disposable {
382 self.register("documentHighlight", &selector)
383 }
384
385 pub fn register_document_symbol_provider(&self, selector:DocumentSelector) -> Disposable {
387 self.register("documentSymbol", &selector)
388 }
389
390 pub fn register_workspace_symbol_provider(&self) -> Disposable { self.register("workspaceSymbol", &Vec::new()) }
392
393 pub fn register_rename_provider(&self, selector:DocumentSelector) -> Disposable {
395 self.register("rename", &selector)
396 }
397
398 pub fn register_document_formatting_edit_provider(&self, selector:DocumentSelector) -> Disposable {
400 self.register("documentFormatting", &selector)
401 }
402
403 pub fn register_document_range_formatting_edit_provider(&self, selector:DocumentSelector) -> Disposable {
405 self.register("documentRangeFormatting", &selector)
406 }
407
408 pub fn register_on_type_formatting_edit_provider(
410 &self,
411 selector:DocumentSelector,
412 _trigger_characters:Vec<String>,
413 ) -> Disposable {
414 self.register("onTypeFormatting", &selector)
415 }
416
417 pub fn register_signature_help_provider(&self, selector:DocumentSelector) -> Disposable {
419 self.register("signatureHelp", &selector)
420 }
421
422 pub fn register_code_lens_provider(&self, selector:DocumentSelector) -> Disposable {
424 self.register("codeLens", &selector)
425 }
426
427 pub fn register_folding_range_provider(&self, selector:DocumentSelector) -> Disposable {
429 self.register("foldingRange", &selector)
430 }
431
432 pub fn register_selection_range_provider(&self, selector:DocumentSelector) -> Disposable {
434 self.register("selectionRange", &selector)
435 }
436
437 pub fn register_document_semantic_tokens_provider(&self, selector:DocumentSelector) -> Disposable {
439 self.register("semanticTokens", &selector)
440 }
441
442 pub fn register_inlay_hints_provider(&self, selector:DocumentSelector) -> Disposable {
444 self.register("inlayHints", &selector)
445 }
446
447 pub fn register_type_hierarchy_provider(&self, selector:DocumentSelector) -> Disposable {
449 self.register("typeHierarchy", &selector)
450 }
451
452 pub fn register_call_hierarchy_provider(&self, selector:DocumentSelector) -> Disposable {
454 self.register("callHierarchy", &selector)
455 }
456
457 pub fn register_linked_editing_range_provider(&self, selector:DocumentSelector) -> Disposable {
459 self.register("linkedEditingRange", &selector)
460 }
461
462 pub fn register_declaration_provider(&self, selector:DocumentSelector) -> Disposable {
464 self.register("declaration", &selector)
465 }
466
467 pub fn register_implementation_provider(&self, selector:DocumentSelector) -> Disposable {
469 self.register("implementation", &selector)
470 }
471
472 pub fn register_type_definition_provider(&self, selector:DocumentSelector) -> Disposable {
474 self.register("typeDefinition", &selector)
475 }
476
477 pub fn create_diagnostic_collection(&self, name:Option<String>) -> DiagnosticCollection {
479 DiagnosticCollection::new(name)
480 }
481
482 pub fn set_language_configuration(&self, language:String) -> Disposable {
484 self.register(
485 "languageConfiguration",
486 &vec![DocumentFilter { language:Some(language), scheme:None, pattern:None }],
487 )
488 }
489}
490
491#[derive(Debug, Clone, Serialize, Deserialize)]
493pub struct DocumentFilter {
494 pub language:Option<String>,
496
497 pub scheme:Option<String>,
499
500 pub pattern:Option<String>,
502}
503
504pub type DocumentSelector = Vec<DocumentFilter>;
506
507pub trait CompletionItemProvider: Send + Sync {
509 fn provide_completion_items(
522 &self,
523 document:TextDocumentIdentifier,
524 position:Position,
525 context:CompletionContext,
526 token:Option<String>,
527 ) -> Vec<CompletionItem>;
528}
529
530#[derive(Debug, Clone, Serialize, Deserialize)]
532pub struct CompletionContext {
533 #[serde(rename = "triggerKind")]
535 pub trigger_kind:CompletionTriggerKind,
536
537 #[serde(rename = "triggerCharacter")]
539 pub trigger_character:Option<String>,
540}
541
542#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
544pub enum CompletionTriggerKind {
545 #[serde(rename = "Invoke")]
547 Invoke = 0,
548
549 #[serde(rename = "TriggerCharacter")]
551 TriggerCharacter = 1,
552
553 #[serde(rename = "TriggerForIncompleteCompletions")]
555 TriggerForIncompleteCompletions = 2,
556}
557
558#[derive(Debug, Clone)]
560pub struct DiagnosticCollection {
561 #[allow(dead_code)]
563 name:Option<String>,
564}
565
566impl DiagnosticCollection {
567 pub fn new(name:Option<String>) -> Self { Self { name } }
573
574 pub fn set(&self, _uri:String, _diagnostics:Vec<Diagnostic>) {
576 }
578
579 pub fn delete(&self, _uri:String) {
581 }
583
584 pub fn clear(&self) {
586 }
588
589 pub fn dispose(&self) {
591 }
593}
594
595pub struct Disposable {
600 callback:Option<Box<dyn FnOnce() + Send + Sync>>,
601}
602
603impl std::fmt::Debug for Disposable {
604 fn fmt(&self, f:&mut std::fmt::Formatter<'_>) -> std::fmt::Result {
605 f.debug_struct("Disposable")
606 .field("has_callback", &self.callback.is_some())
607 .finish()
608 }
609}
610
611impl Clone for Disposable {
612 fn clone(&self) -> Self { Self { callback:None } }
615}
616
617impl Disposable {
618 pub fn new() -> Self { Self { callback:None } }
620
621 pub fn with_callback(callback:Box<dyn FnOnce() + Send + Sync>) -> Self { Self { callback:Some(callback) } }
623
624 pub fn dispose(mut self) {
626 if let Some(Callback) = self.callback.take() {
627 Callback();
628 }
629 }
630}
631
632impl Default for Disposable {
633 fn default() -> Self { Self::new() }
634}
635
636#[derive(Debug, Clone)]
638pub struct ExtensionNamespace;
639
640impl ExtensionNamespace {
641 pub fn new() -> Self { Self }
643
644 pub fn all(&self) -> Vec<Extension> { Vec::new() }
646
647 pub fn get_extension(&self, _extension_id:String) -> Option<Extension> { None }
649}
650
651#[derive(Debug, Clone, Serialize, Deserialize)]
653pub struct Extension {
654 pub id:String,
656
657 #[serde(rename = "extensionPath")]
659 pub extension_path:String,
660
661 pub is_active:bool,
663
664 #[serde(rename = "packageJSON")]
666 pub package_json:serde_json::Value,
667}
668
669#[derive(Debug, Clone)]
671pub struct Env;
672
673impl Env {
674 pub fn new() -> Self { Self }
676
677 pub fn get_env_var(&self, name:String) -> Option<String> { std::env::var(name).ok() }
679
680 pub fn is_windows(&self) -> bool { cfg!(windows) }
682
683 pub fn is_mac(&self) -> bool { cfg!(target_os = "macos") }
685
686 pub fn is_linux(&self) -> bool { cfg!(target_os = "linux") }
688
689 pub fn app_name(&self) -> String { "VS Code".to_string() }
691
692 pub fn app_root(&self) -> Option<String> { std::env::var("VSCODE_APP_ROOT").ok() }
694}
695
696#[cfg(test)]
697mod tests {
698 use super::*;
699
700 #[test]
701 fn test_vscode_api_creation() {
702 let _api = VSCodeAPI::new();
703 }
705
706 #[test]
707 fn test_position_operations() {
708 let pos = Position::new(5, 10);
709 assert_eq!(pos.line, 5);
710 assert_eq!(pos.character, 10);
711 }
712
713 #[test]
714 fn test_output_channel() {
715 let channel = OutputChannel::new("test".to_string());
716 channel.append_line("test message");
717 }
718
719 #[test]
720 fn test_disposable() {
721 let disposable = Disposable::new();
722 disposable.dispose();
723 }
724}