1#![allow(non_snake_case, non_camel_case_types)]
17
18use std::sync::Arc;
19
20use Common::{
21 Environment::Requires::Requires,
22 Error::CommonError::CommonError,
23 IPC::IPCProvider::IPCProvider,
24 LanguageFeature::{
25 DTO::{
26 CompletionContextDTO::CompletionContextDTO,
27 CompletionListDTO::CompletionListDTO,
28 HoverResultDTO::HoverResultDTO,
29 LocationDTO::LocationDTO,
30 PositionDTO::PositionDTO,
31 ProviderType::ProviderType,
32 TextEditDTO::TextEditDTO,
33 },
34 LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
35 },
36};
37use async_trait::async_trait;
38use log::{debug, info, warn};
39use serde::de::DeserializeOwned;
40use serde_json::{Value, json};
41use url::Url;
42
43use super::{MountainEnvironment::MountainEnvironment, Utility};
44use crate::ApplicationState::DTO::ProviderRegistrationDTO::ProviderRegistrationDTO;
45
46#[async_trait]
47impl LanguageFeatureProviderRegistry for MountainEnvironment {
48 async fn RegisterProvider(
49 &self,
50
51 SideCarIdentifier:String,
52
53 ProviderType:ProviderType,
54
55 SelectorDTO:Value,
56
57 ExtensionIdentifierDTO:Value,
58
59 OptionsDTO:Option<Value>,
60 ) -> Result<u32, CommonError> {
61 let Handle = self.ApplicationState.GetNextProviderHandle();
62
63 info!(
64 "[LangFeatureProvider] Registering {:?} provider from '{}' with new handle {}",
65 ProviderType, SideCarIdentifier, Handle
66 );
67
68 let NewRegistration = ProviderRegistrationDTO {
69 Handle,
70
71 ProviderType,
72
73 Selector:SelectorDTO,
74
75 SideCarIdentifier,
76
77 Options:OptionsDTO,
78
79 ExtensionIdentifier:ExtensionIdentifierDTO,
80 };
81
82 self.ApplicationState
83 .LanguageProviders
84 .lock()
85 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
86 .insert(Handle, NewRegistration);
87
88 Ok(Handle)
89 }
90
91 async fn UnregisterProvider(&self, Handle:u32) -> Result<(), CommonError> {
92 info!("[LangFeatureProvider] Unregistering provider with handle {}", Handle);
93
94 if self
95 .ApplicationState
96 .LanguageProviders
97 .lock()
98 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
99 .remove(&Handle)
100 .is_none()
101 {
102 warn!(
103 "[LangFeatureProvider] Attempted to unregister a provider with handle {} that was not found.",
104 Handle
105 );
106 }
107 Ok(())
108 }
109
110 async fn ProvideHover(
112 &self,
113
114 DocumentURI:Url,
115
116 PositionDTO:PositionDTO,
117 ) -> Result<Option<HoverResultDTO>, CommonError> {
118 InvokeProvider(self, ProviderType::Hover, &DocumentURI, json!([PositionDTO])).await
119 }
120
121 async fn ProvideCompletions(
122 &self,
123
124 DocumentURI:Url,
125
126 PositionDTO:PositionDTO,
127
128 ContextDTO:CompletionContextDTO,
129
130 CancellationTokenValue:Option<Value>,
131 ) -> Result<Option<CompletionListDTO>, CommonError> {
132 InvokeProvider(
133 self,
134 ProviderType::Completion,
135 &DocumentURI,
136 json!([PositionDTO, ContextDTO, CancellationTokenValue]),
137 )
138 .await
139 }
140
141 async fn ProvideDefinition(
142 &self,
143
144 DocumentURI:Url,
145
146 PositionDTO:PositionDTO,
147 ) -> Result<Option<Vec<LocationDTO>>, CommonError> {
148 InvokeProvider(self, ProviderType::Definition, &DocumentURI, json!([PositionDTO])).await
149 }
150
151 async fn ProvideReferences(
152 &self,
153
154 DocumentURI:Url,
155
156 PositionDTO:PositionDTO,
157
158 ContextDTO:Value,
159 ) -> Result<Option<Vec<LocationDTO>>, CommonError> {
160 InvokeProvider(self, ProviderType::References, &DocumentURI, json!([PositionDTO, ContextDTO])).await
161 }
162
163 async fn ProvideDocumentFormattingEdits(
164 &self,
165
166 DocumentURI:Url,
167
168 OptionsDTO:Value,
169 ) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
170 InvokeProvider(self, ProviderType::DocumentFormatting, &DocumentURI, json!([OptionsDTO])).await
171 }
172
173 async fn ProvideDocumentRangeFormattingEdits(
174 &self,
175
176 DocumentURI:Url,
177
178 RangeDTO:Value,
179
180 OptionsDTO:Value,
181 ) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
182 InvokeProvider(
183 self,
184 ProviderType::DocumentRangeFormatting,
185 &DocumentURI,
186 json!([RangeDTO, OptionsDTO]),
187 )
188 .await
189 }
190
191 async fn ProvideCodeActions(
193 &self,
194
195 _DocumentURI:Url,
196
197 _RangeOrSelectionDTO:Value,
198
199 _ContextDTO:Value,
200 ) -> Result<Option<Value>, CommonError> {
201 warn!("[LangFeatureProvider] ProvideCodeActions is not implemented.");
202
203 Ok(None)
204 }
205
206 async fn ProvideCodeLenses(&self, _DocumentURI:Url) -> Result<Option<Value>, CommonError> {
207 warn!("[LangFeatureProvider] ProvideCodeLenses is not implemented.");
208
209 Ok(None)
210 }
211
212 async fn ProvideDocumentHighlights(
213 &self,
214
215 _DocumentURI:Url,
216
217 _PositionDTO:PositionDTO,
218 ) -> Result<Option<Value>, CommonError> {
219 warn!("[LangFeatureProvider] ProvideDocumentHighlights is not implemented.");
220
221 Ok(None)
222 }
223
224 async fn ProvideDocumentLinks(&self, _DocumentURI:Url) -> Result<Option<Value>, CommonError> {
225 warn!("[LangFeatureProvider] ProvideDocumentLinks is not implemented.");
226
227 Ok(None)
228 }
229
230 async fn PrepareRename(&self, _DocumentURI:Url, _PositionDTO:PositionDTO) -> Result<Option<Value>, CommonError> {
231 warn!("[LangFeatureProvider] PrepareRename is not implemented.");
232
233 Ok(None)
234 }
235}
236
237fn FindBestProvider(
241 Environment:&MountainEnvironment,
242
243 ProviderType:ProviderType,
244
245 DocumentURI:&Url,
246) -> Result<Option<ProviderRegistrationDTO>, CommonError> {
247 let Providers = Environment
248 .ApplicationState
249 .LanguageProviders
250 .lock()
251 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?;
252
253 let Document = Environment
254 .ApplicationState
255 .OpenDocuments
256 .lock()
257 .map_err(Utility::MapApplicationStateLockErrorToCommonError)?
258 .get(DocumentURI.as_str())
259 .cloned();
260
261 if let Some(doc) = Document {
262 for Provider in Providers.values() {
266 if Provider.ProviderType == ProviderType {
267 if let Some(SelectorArray) = Provider.Selector.as_array() {
268 for Selector in SelectorArray {
269 if let Some(Lang) = Selector.get("language").and_then(Value::as_str) {
270 if Lang == doc.LanguageIdentifier {
271 debug!("Found provider with handle {} for document {}", Provider.Handle, DocumentURI);
272
273 return Ok(Some(Provider.clone()));
274 }
275 }
276 }
278 }
279 }
280 }
281 }
282 warn!("No provider found for {:?} on document {}", ProviderType, DocumentURI);
283
284 Ok(None)
285}
286
287async fn InvokeProvider<TResponse:DeserializeOwned>(
290 Environment:&MountainEnvironment,
291
292 ProviderType:ProviderType,
293
294 DocumentURI:&Url,
295
296 mut ProviderArguments:Value,
297) -> Result<Option<TResponse>, CommonError> {
298 if let Some(Provider) = FindBestProvider(Environment, ProviderType, DocumentURI)? {
299 let RPCMethod = format!("$provide{}", Provider.ProviderType.to_string());
300
301 let URIComponents = json!({ "external": DocumentURI.to_string(), "$mid": 1 });
302
303 let ArgumentsVector = ProviderArguments.as_array_mut().ok_or_else(|| {
304 CommonError::InvalidArgument {
305 ArgumentName:"ProviderArguments".into(),
306
307 Reason:"Expected provider arguments to be a JSON array.".into(),
308 }
309 })?;
310
311 let mut FinalArgumentsVector = vec![json!(Provider.Handle), URIComponents];
312
313 FinalArgumentsVector.append(ArgumentsVector);
314
315 let FinalArguments = json!(FinalArgumentsVector);
316
317 let IPCProvider:Arc<dyn IPCProvider> = Environment.Require();
318
319 let Response = IPCProvider
320 .SendRequestToSideCar(Provider.SideCarIdentifier, RPCMethod, FinalArguments, 5000)
321 .await?;
322
323 if Response.is_null() {
324 return Ok(None);
325 }
326 serde_json::from_value(Response).map_err(|Error| {
327 CommonError::SerializationError {
328 Description:format!("Failed to deserialize response for {:?}: {}", ProviderType, Error),
329 }
330 })
331 } else {
332 Ok(None)
333 }
334}