1mod lsp;
2mod oxfmt;
3mod oxlint;
4
5use crate::lsp::{OXFMT_SERVER_ID, OXLINT_SERVER_ID, ZedLspSupport};
6use crate::oxfmt::ZedOxfmtLsp;
7use crate::oxlint::ZedOxlintLsp;
8use log::Level;
9use serde_json::Value;
10use simple_logger::init_with_level;
11use std::sync::{Arc, RwLock};
12use zed_extension_api::{
13 Command, Extension, LanguageServerId, Result, Worktree, register_extension,
14 serde_json::{self},
15};
16
17struct OxcExtension {
18 oxfmt_lsp: Arc<RwLock<ZedOxfmtLsp>>,
19 oxlint_lsp: Arc<RwLock<ZedOxlintLsp>>,
20}
21
22impl OxcExtension {
23 fn is_oxfmt_language_server(&self, language_server_id: &LanguageServerId) -> bool {
24 language_server_id.as_ref() == OXFMT_SERVER_ID
25 }
26
27 fn is_oxlint_language_server(&self, language_server_id: &LanguageServerId) -> bool {
28 language_server_id.as_ref() == OXLINT_SERVER_ID
29 }
30
31 fn update_oxfmt_language_server_if_needed(
32 &self,
33 language_server_id: &LanguageServerId,
34 worktree: &Worktree,
35 ) -> Result<()> {
36 let zed_oxfmt_lsp = self.oxfmt_lsp.read().unwrap();
37 if !zed_oxfmt_lsp.exe_exists(worktree)? {
38 zed_oxfmt_lsp.update_extension_language_server_if_outdated(language_server_id)?;
39 }
40 Ok(())
41 }
42
43 fn update_oxlint_language_server_if_needed(
44 &self,
45 language_server_id: &LanguageServerId,
46 worktree: &Worktree,
47 ) -> Result<()> {
48 let zed_oxlint_lsp = self.oxlint_lsp.read().unwrap();
49 if !zed_oxlint_lsp.exe_exists(worktree)? {
50 zed_oxlint_lsp.update_extension_language_server_if_outdated(language_server_id)?;
51 }
52 Ok(())
53 }
54}
55
56impl Extension for OxcExtension {
57 fn new() -> Self
58 where
59 Self: Sized,
60 {
61 init_with_level(Level::Debug).unwrap();
62
63 Self {
64 oxfmt_lsp: Arc::new(RwLock::new(ZedOxfmtLsp::new())),
65 oxlint_lsp: Arc::new(RwLock::new(ZedOxlintLsp::new())),
66 }
67 }
68
69 fn language_server_command(
70 &mut self,
71 language_server_id: &LanguageServerId,
72 worktree: &Worktree,
73 ) -> Result<Command> {
74 if self.is_oxfmt_language_server(language_server_id) {
75 self.update_oxfmt_language_server_if_needed(language_server_id, worktree)?;
76
77 return self
78 .oxfmt_lsp
79 .read()
80 .unwrap()
81 .language_server_command(language_server_id, worktree);
82 }
83
84 if self.is_oxlint_language_server(language_server_id) {
85 self.update_oxlint_language_server_if_needed(language_server_id, worktree)?;
86
87 return self
88 .oxlint_lsp
89 .read()
90 .unwrap()
91 .language_server_command(language_server_id, worktree);
92 }
93
94 Err(format!(
95 "Unsupported language server id: {language_server_id:?}"
96 ))
97 }
98
99 fn language_server_initialization_options(
100 &mut self,
101 language_server_id: &LanguageServerId,
102 worktree: &Worktree,
103 ) -> Result<Option<Value>> {
104 if self.is_oxfmt_language_server(language_server_id) {
105 return self
106 .oxfmt_lsp
107 .read()
108 .unwrap()
109 .language_server_initialization_options(language_server_id, worktree);
110 }
111
112 if self.is_oxlint_language_server(language_server_id) {
113 return self
114 .oxlint_lsp
115 .read()
116 .unwrap()
117 .language_server_initialization_options(language_server_id, worktree);
118 }
119
120 Err(format!(
121 "Unsupported language server id: {language_server_id:?}"
122 ))
123 }
124
125 fn language_server_workspace_configuration(
126 &mut self,
127 language_server_id: &LanguageServerId,
128 worktree: &Worktree,
129 ) -> Result<Option<Value>> {
130 if self.is_oxfmt_language_server(language_server_id) {
131 return self
132 .oxfmt_lsp
133 .read()
134 .unwrap()
135 .language_server_workspace_configuration(language_server_id, worktree);
136 }
137
138 if self.is_oxlint_language_server(language_server_id) {
139 return self
140 .oxlint_lsp
141 .read()
142 .unwrap()
143 .language_server_workspace_configuration(language_server_id, worktree);
144 }
145
146 Err(format!(
147 "Unsupported language server id: {language_server_id:?}"
148 ))
149 }
150}
151
152register_extension!(OxcExtension);