1use std::sync::Arc;
8
9use serde::{Deserialize, Serialize};
10
11use crate::API::types::*;
12
13#[derive(Debug, Clone)]
15pub struct VSCodeAPI {
16 pub commands:Arc<CommandNamespace>,
18 pub window:Arc<Window>,
20 pub workspace:Arc<Workspace>,
22 pub languages:Arc<LanguageNamespace>,
24 pub extensions:Arc<ExtensionNamespace>,
26 pub env:Arc<Env>,
28}
29
30impl VSCodeAPI {
31 pub fn new() -> Self {
33 Self {
34 commands:Arc::new(CommandNamespace::new()),
35 window:Arc::new(Window::new()),
36 workspace:Arc::new(Workspace::new()),
37 languages:Arc::new(LanguageNamespace::new()),
38 extensions:Arc::new(ExtensionNamespace::new()),
39 env:Arc::new(Env::new()),
40 }
41 }
42}
43
44impl Default for VSCodeAPI {
45 fn default() -> Self { Self::new() }
46}
47
48#[derive(Debug, Clone)]
50pub struct CommandNamespace;
51
52impl CommandNamespace {
53 pub fn new() -> Self { Self }
55
56 pub fn register_command(&self, command_id:String, _callback:CommandCallback) -> Result<Command, String> {
58 Ok(Command { id:command_id.clone() })
59 }
60
61 pub async fn execute_command<T:serde::de::DeserializeOwned>(
63 &self,
64 command_id:String,
65 _args:Vec<serde_json::Value>,
66 ) -> Result<T, String> {
67 Err(format!("Command not implemented: {}", command_id))
69 }
70}
71
72pub type CommandCallback = Box<dyn Fn(Vec<serde_json::Value>) -> Result<serde_json::Value, String> + Send + Sync>;
74
75#[derive(Debug, Clone)]
77pub struct Command {
78 pub id:String,
80}
81
82#[derive(Debug, Clone)]
84pub struct Window;
85
86impl Window {
87 pub fn new() -> Self { Self }
89
90 pub async fn show_information_message(&self, _message:String) -> Result<String, String> {
92 Ok("OK".to_string())
94 }
95
96 pub async fn show_warning_message(&self, _message:String) -> Result<String, String> {
98 Ok("OK".to_string())
100 }
101
102 pub async fn show_error_message(&self, _message:String) -> Result<String, String> {
104 Ok("OK".to_string())
106 }
107
108 pub fn create_output_channel(&self, name:String) -> OutputChannel { OutputChannel::new(name) }
110}
111
112#[derive(Debug, Clone)]
114pub struct OutputChannel {
115 name:String,
117}
118
119impl OutputChannel {
120 pub fn new(name:String) -> Self { Self { name } }
126
127 pub fn append_line(&self, line:&str) {
129 tracing::info!("[{}] {}", self.name, line);
130 }
131
132 pub fn append(&self, value:&str) {
134 tracing::info!("[{}] {}", self.name, value);
135 }
136
137 pub fn show(&self) {
139 }
141
142 pub fn hide(&self) {
144 }
146
147 pub fn dispose(&self) {
149 }
151}
152
153#[derive(Debug, Clone)]
155pub struct Workspace;
156
157impl Workspace {
158 pub fn new() -> Self { Self }
160
161 pub fn workspace_folders(&self) -> Vec<WorkspaceFolder> {
163 Vec::new()
165 }
166
167 pub fn get_configuration(&self, section:Option<String>) -> WorkspaceConfiguration {
169 WorkspaceConfiguration::new(section)
170 }
171}
172
173#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct WorkspaceFolder {
176 pub uri:String,
178
179 pub name:String,
181
182 pub index:u32,
184}
185
186#[derive(Debug, Clone)]
188pub struct WorkspaceConfiguration {
189 #[allow(dead_code)]
191 section:Option<String>,
192}
193
194impl WorkspaceConfiguration {
195 pub fn new(section:Option<String>) -> Self { Self { section } }
201
202 pub fn get<T:serde::de::DeserializeOwned>(&self, _key:String) -> Result<T, String> {
204 Err("Configuration not implemented".to_string())
206 }
207
208 pub fn has(&self, _key:String) -> bool { false }
210
211 pub async fn update(&self, _key:String, _value:serde_json::Value) -> Result<(), String> {
213 Err("Update configuration not implemented".to_string())
215 }
216}
217
218#[derive(Debug, Clone)]
222pub struct LanguageNamespace;
223
224impl LanguageNamespace {
225 pub fn new() -> Self { Self }
227
228 pub async fn register_completion_item_provider<T:CompletionItemProvider>(
230 &self,
231 _selector:DocumentSelector,
232 _provider:T,
233 _trigger_characters:Option<Vec<String>>,
234 ) -> Result<Disposable, String> {
235 Ok(Disposable::new())
236 }
237
238 pub fn register_hover_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
240
241 pub fn register_definition_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
243
244 pub fn register_reference_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
246
247 pub fn register_code_actions_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
249
250 pub fn register_document_highlight_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
252
253 pub fn register_document_symbol_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
255
256 pub fn register_workspace_symbol_provider(&self) -> Disposable { Disposable::new() }
258
259 pub fn register_rename_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
261
262 pub fn register_document_formatting_edit_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
264
265 pub fn register_document_range_formatting_edit_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
267
268 pub fn register_on_type_formatting_edit_provider(&self, _selector:DocumentSelector, _trigger_characters:Vec<String>) -> Disposable { Disposable::new() }
270
271 pub fn register_signature_help_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
273
274 pub fn register_code_lens_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
276
277 pub fn register_folding_range_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
279
280 pub fn register_selection_range_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
282
283 pub fn register_document_semantic_tokens_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
285
286 pub fn register_inlay_hints_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
288
289 pub fn register_type_hierarchy_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
291
292 pub fn register_call_hierarchy_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
294
295 pub fn register_linked_editing_range_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
297
298 pub fn register_declaration_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
300
301 pub fn register_implementation_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
303
304 pub fn register_type_definition_provider(&self, _selector:DocumentSelector) -> Disposable { Disposable::new() }
306
307 pub fn create_diagnostic_collection(&self, name:Option<String>) -> DiagnosticCollection {
309 DiagnosticCollection::new(name)
310 }
311
312 pub fn set_language_configuration(&self, _language:String) -> Disposable { Disposable::new() }
314}
315
316#[derive(Debug, Clone, Serialize, Deserialize)]
318pub struct DocumentFilter {
319 pub language:Option<String>,
321
322 pub scheme:Option<String>,
324
325 pub pattern:Option<String>,
327}
328
329pub type DocumentSelector = Vec<DocumentFilter>;
331
332pub trait CompletionItemProvider: Send + Sync {
334 fn provide_completion_items(
347 &self,
348 document:TextDocumentIdentifier,
349 position:Position,
350 context:CompletionContext,
351 token:Option<String>,
352 ) -> Vec<CompletionItem>;
353}
354
355#[derive(Debug, Clone, Serialize, Deserialize)]
357pub struct CompletionContext {
358 #[serde(rename = "triggerKind")]
360 pub trigger_kind:CompletionTriggerKind,
361
362 #[serde(rename = "triggerCharacter")]
364 pub trigger_character:Option<String>,
365}
366
367#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
369pub enum CompletionTriggerKind {
370 #[serde(rename = "Invoke")]
372 Invoke = 0,
373
374 #[serde(rename = "TriggerCharacter")]
376 TriggerCharacter = 1,
377
378 #[serde(rename = "TriggerForIncompleteCompletions")]
380 TriggerForIncompleteCompletions = 2,
381}
382
383#[derive(Debug, Clone)]
385pub struct DiagnosticCollection {
386 #[allow(dead_code)]
388 name:Option<String>,
389}
390
391impl DiagnosticCollection {
392 pub fn new(name:Option<String>) -> Self { Self { name } }
398
399 pub fn set(&self, _uri:String, _diagnostics:Vec<Diagnostic>) {
401 }
403
404 pub fn delete(&self, _uri:String) {
406 }
408
409 pub fn clear(&self) {
411 }
413
414 pub fn dispose(&self) {
416 }
418}
419
420#[derive(Debug, Clone)]
422pub struct Disposable;
423
424impl Disposable {
425 pub fn new() -> Self { Self }
427
428 pub fn dispose(&self) {
430 }
432}
433
434#[derive(Debug, Clone)]
436pub struct ExtensionNamespace;
437
438impl ExtensionNamespace {
439 pub fn new() -> Self { Self }
441
442 pub fn all(&self) -> Vec<Extension> { Vec::new() }
444
445 pub fn get_extension(&self, _extension_id:String) -> Option<Extension> { None }
447}
448
449#[derive(Debug, Clone, Serialize, Deserialize)]
451pub struct Extension {
452 pub id:String,
454
455 #[serde(rename = "extensionPath")]
457 pub extension_path:String,
458
459 pub is_active:bool,
461
462 #[serde(rename = "packageJSON")]
464 pub package_json:serde_json::Value,
465}
466
467#[derive(Debug, Clone)]
469pub struct Env;
470
471impl Env {
472 pub fn new() -> Self { Self }
474
475 pub fn get_env_var(&self, name:String) -> Option<String> { std::env::var(name).ok() }
477
478 pub fn is_windows(&self) -> bool { cfg!(windows) }
480
481 pub fn is_mac(&self) -> bool { cfg!(target_os = "macos") }
483
484 pub fn is_linux(&self) -> bool { cfg!(target_os = "linux") }
486
487 pub fn app_name(&self) -> String { "VS Code".to_string() }
489
490 pub fn app_root(&self) -> Option<String> { std::env::var("VSCODE_APP_ROOT").ok() }
492}
493
494#[cfg(test)]
495mod tests {
496 use super::*;
497
498 #[test]
499 fn test_vscode_api_creation() {
500 let _api = VSCodeAPI::new();
501 }
503
504 #[test]
505 fn test_position_operations() {
506 let pos = Position::new(5, 10);
507 assert_eq!(pos.line, 5);
508 assert_eq!(pos.character, 10);
509 }
510
511 #[test]
512 fn test_output_channel() {
513 let channel = OutputChannel::new("test".to_string());
514 channel.append_line("test message");
515 }
516
517 #[test]
518 fn test_disposable() {
519 let disposable = Disposable::new();
520 disposable.dispose();
521 }
522}