Skip to main content

Mountain/Environment/LanguageFeatureProvider/
FeatureMethods.rs

1//! All LSP feature method implementations.
2
3use std::sync::Arc;
4
5use CommonLibrary::{
6	Environment::Requires::Requires,
7	Error::CommonError::CommonError,
8	IPC::IPCProvider::IPCProvider,
9	LanguageFeature::DTO::{
10		CompletionContextDTO::CompletionContextDTO,
11		CompletionListDTO::CompletionListDTO,
12		HoverResultDTO::HoverResultDTO,
13		LocationDTO::LocationDTO,
14		PositionDTO::PositionDTO,
15		ProviderType::ProviderType,
16		TextEditDTO::TextEditDTO,
17	},
18};
19use serde_json::{Value, json};
20use url::Url;
21
22use crate::ApplicationState::DTO::ProviderRegistrationDTO::ProviderRegistrationDTO;
23
24// All feature methods delegate to generic invoke pattern
25
26pub(super) async fn provide_code_actions(
27	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
28	document_uri:Url,
29	range_or_selection_dto:Value,
30	context_dto:Value,
31) -> Result<Option<Value>, CommonError> {
32	let provider =
33		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CodeAction).await?;
34	match provider {
35		Some(registration) => {
36			let response = invoke_provider(
37				environment,
38				&registration,
39				vec![
40					json!(registration.Handle),
41					json!({ "external": document_uri.to_string(), "$mid": 1 }),
42					range_or_selection_dto,
43					context_dto,
44				],
45			)
46			.await?;
47			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
48		},
49		None => Ok(None),
50	}
51}
52
53pub(super) async fn provide_code_lenses(
54	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
55	document_uri:Url,
56) -> Result<Option<Value>, CommonError> {
57	let provider =
58		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CodeLens).await?;
59	match provider {
60		Some(registration) => {
61			let response = invoke_provider(
62				environment,
63				&registration,
64				vec![
65					json!(registration.Handle),
66					json!({ "external": document_uri.to_string(), "$mid": 1 }),
67				],
68			)
69			.await?;
70			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
71		},
72		None => Ok(None),
73	}
74}
75
76pub(super) async fn provide_completions(
77	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
78	document_uri:Url,
79	position_dto:PositionDTO,
80	context_dto:CompletionContextDTO,
81	cancellation_token_value:Option<Value>,
82) -> Result<Option<CompletionListDTO>, CommonError> {
83	let provider =
84		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Completion).await?;
85	match provider {
86		Some(registration) => {
87			let response = invoke_provider(
88				environment,
89				&registration,
90				vec![
91					json!(registration.Handle),
92					json!({ "external": document_uri.to_string(), "$mid": 1 }),
93					json!(position_dto),
94					json!(context_dto),
95					cancellation_token_value.unwrap_or_else(|| json!(null)),
96				],
97			)
98			.await?;
99			if response.is_null() {
100				Ok(None)
101			} else {
102				serde_json::from_value(response).map_err(|error| {
103					CommonError::SerializationError {
104						Description:format!("Failed to deserialize CompletionListDTO: {}", error),
105					}
106				})
107			}
108		},
109		None => Ok(None),
110	}
111}
112
113pub(super) async fn provide_definition(
114	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
115	document_uri:Url,
116	position_dto:PositionDTO,
117) -> Result<Option<Vec<LocationDTO>>, CommonError> {
118	let provider =
119		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Definition).await?;
120	match provider {
121		Some(registration) => {
122			let response = invoke_provider(
123				environment,
124				&registration,
125				vec![
126					json!(registration.Handle),
127					json!({ "external": document_uri.to_string(), "$mid": 1 }),
128					json!(position_dto),
129				],
130			)
131			.await?;
132			if response.is_null() {
133				Ok(None)
134			} else {
135				serde_json::from_value(response).map_err(|error| {
136					CommonError::SerializationError {
137						Description:format!("Failed to deserialize Vec<LocationDTO>: {}", error),
138					}
139				})
140			}
141		},
142		None => Ok(None),
143	}
144}
145
146pub(super) async fn provide_document_formatting_edits(
147	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
148	document_uri:Url,
149	options_dto:Value,
150) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
151	let provider =
152		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentFormatting)
153			.await?;
154	match provider {
155		Some(registration) => {
156			let response = invoke_provider(
157				environment,
158				&registration,
159				vec![
160					json!(registration.Handle),
161					json!({ "external": document_uri.to_string(), "$mid": 1 }),
162					options_dto,
163				],
164			)
165			.await?;
166			if response.is_null() {
167				Ok(None)
168			} else {
169				serde_json::from_value(response).map_err(|error| {
170					CommonError::SerializationError {
171						Description:format!("Failed to deserialize Vec<TextEditDTO>: {}", error),
172					}
173				})
174			}
175		},
176		None => Ok(None),
177	}
178}
179
180pub(super) async fn provide_document_highlights(
181	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
182	document_uri:Url,
183	position_dto:PositionDTO,
184) -> Result<Option<Value>, CommonError> {
185	let provider =
186		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentHighlight)
187			.await?;
188	match provider {
189		Some(registration) => {
190			let response = invoke_provider(
191				environment,
192				&registration,
193				vec![
194					json!(registration.Handle),
195					json!({ "external": document_uri.to_string(), "$mid": 1 }),
196					json!(position_dto),
197				],
198			)
199			.await?;
200			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
201		},
202		None => Ok(None),
203	}
204}
205
206pub(super) async fn provide_document_links(
207	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
208	document_uri:Url,
209) -> Result<Option<Value>, CommonError> {
210	let provider =
211		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentLink).await?;
212	match provider {
213		Some(registration) => {
214			let response = invoke_provider(
215				environment,
216				&registration,
217				vec![
218					json!(registration.Handle),
219					json!({ "external": document_uri.to_string(), "$mid": 1 }),
220				],
221			)
222			.await?;
223			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
224		},
225		None => Ok(None),
226	}
227}
228
229pub(super) async fn provide_document_range_formatting_edits(
230	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
231	document_uri:Url,
232	range_dto:Value,
233	options_dto:Value,
234) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
235	let provider =
236		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentRangeFormatting)
237			.await?;
238	match provider {
239		Some(registration) => {
240			let response = invoke_provider(
241				environment,
242				&registration,
243				vec![
244					json!(registration.Handle),
245					json!({ "external": document_uri.to_string(), "$mid": 1 }),
246					range_dto,
247					options_dto,
248				],
249			)
250			.await?;
251			if response.is_null() {
252				Ok(None)
253			} else {
254				serde_json::from_value(response).map_err(|error| {
255					CommonError::SerializationError {
256						Description:format!("Failed to deserialize Vec<TextEditDTO>: {}", error),
257					}
258				})
259			}
260		},
261		None => Ok(None),
262	}
263}
264
265pub(super) async fn provide_hover(
266	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
267	document_uri:Url,
268	position_dto:PositionDTO,
269) -> Result<Option<HoverResultDTO>, CommonError> {
270	let provider =
271		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Hover).await?;
272	match provider {
273		Some(registration) => {
274			let response = invoke_provider(
275				environment,
276				&registration,
277				vec![
278					json!(registration.Handle),
279					json!({ "external": document_uri.to_string(), "$mid": 1 }),
280					json!(position_dto),
281				],
282			)
283			.await?;
284			if response.is_null() {
285				Ok(None)
286			} else {
287				serde_json::from_value(response).map_err(|error| {
288					CommonError::SerializationError {
289						Description:format!("Failed to deserialize HoverResultDTO: {}", error),
290					}
291				})
292			}
293		},
294		None => Ok(None),
295	}
296}
297
298pub(super) async fn provide_references(
299	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
300	document_uri:Url,
301	position_dto:PositionDTO,
302	context_dto:Value,
303) -> Result<Option<Vec<LocationDTO>>, CommonError> {
304	let provider =
305		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::References).await?;
306	match provider {
307		Some(registration) => {
308			let response = invoke_provider(
309				environment,
310				&registration,
311				vec![
312					json!(registration.Handle),
313					json!({ "external": document_uri.to_string(), "$mid": 1 }),
314					json!(position_dto),
315					context_dto,
316				],
317			)
318			.await?;
319			if response.is_null() {
320				Ok(None)
321			} else {
322				serde_json::from_value(response).map_err(|error| {
323					CommonError::SerializationError {
324						Description:format!("Failed to deserialize Vec<LocationDTO>: {}", error),
325					}
326				})
327			}
328		},
329		None => Ok(None),
330	}
331}
332
333pub(super) async fn prepare_rename(
334	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
335	document_uri:Url,
336	position_dto:PositionDTO,
337) -> Result<Option<Value>, CommonError> {
338	let provider =
339		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Rename).await?;
340	match provider {
341		Some(registration) => {
342			let response = invoke_provider(
343				environment,
344				&registration,
345				vec![
346					json!(registration.Handle),
347					json!({ "external": document_uri.to_string(), "$mid": 1 }),
348					json!(position_dto),
349				],
350			)
351			.await?;
352			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
353		},
354		None => Ok(None),
355	}
356}
357
358pub(super) async fn provide_rename_edits(
359	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
360	document_uri:Url,
361	position_dto:PositionDTO,
362	new_name:String,
363) -> Result<Option<Value>, CommonError> {
364	let provider =
365		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Rename).await?;
366	match provider {
367		Some(registration) => {
368			let response = invoke_provider(
369				environment,
370				&registration,
371				vec![
372					json!(registration.Handle),
373					json!({ "external": document_uri.to_string(), "$mid": 1 }),
374					json!(position_dto),
375					json!(new_name),
376				],
377			)
378			.await?;
379			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
380		},
381		None => Ok(None),
382	}
383}
384
385pub(super) async fn provide_document_symbols(
386	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
387	document_uri:Url,
388) -> Result<Option<Value>, CommonError> {
389	let provider =
390		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentSymbol).await?;
391	match provider {
392		Some(registration) => {
393			let response = invoke_provider(
394				environment,
395				&registration,
396				vec![
397					json!(registration.Handle),
398					json!({ "external": document_uri.to_string(), "$mid": 1 }),
399				],
400			)
401			.await?;
402			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
403		},
404		None => Ok(None),
405	}
406}
407
408pub(super) async fn provide_workspace_symbols(
409	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
410	query:String,
411) -> Result<Option<Value>, CommonError> {
412	// Workspace symbols don't have a specific document URI — use a dummy lookup.
413	// The provider is registered globally, so we pick the first WorkspaceSymbol
414	// provider.
415	let MatchingRegistration = {
416		let providers = environment
417			.ApplicationState
418			.Extension
419			.ProviderRegistration
420			.LanguageProviders
421			.lock()
422			.map_err(crate::Environment::Utility::MapApplicationStateLockErrorToCommonError)?;
423		providers
424			.values()
425			.find(|p| p.ProviderType == ProviderType::WorkspaceSymbol)
426			.cloned()
427	};
428	match MatchingRegistration {
429		Some(registration) => {
430			let response =
431				invoke_provider(environment, &registration, vec![json!(registration.Handle), json!(query)]).await?;
432			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
433		},
434		None => Ok(None),
435	}
436}
437
438pub(super) async fn provide_signature_help(
439	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
440	document_uri:Url,
441	position_dto:PositionDTO,
442	context_dto:Value,
443) -> Result<Option<Value>, CommonError> {
444	let provider =
445		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::SignatureHelp).await?;
446	match provider {
447		Some(registration) => {
448			let response = invoke_provider(
449				environment,
450				&registration,
451				vec![
452					json!(registration.Handle),
453					json!({ "external": document_uri.to_string(), "$mid": 1 }),
454					json!(position_dto),
455					context_dto,
456				],
457			)
458			.await?;
459			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
460		},
461		None => Ok(None),
462	}
463}
464
465pub(super) async fn provide_folding_ranges(
466	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
467	document_uri:Url,
468) -> Result<Option<Value>, CommonError> {
469	let provider =
470		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::FoldingRange).await?;
471	match provider {
472		Some(registration) => {
473			let response = invoke_provider(
474				environment,
475				&registration,
476				vec![
477					json!(registration.Handle),
478					json!({ "external": document_uri.to_string(), "$mid": 1 }),
479				],
480			)
481			.await?;
482			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
483		},
484		None => Ok(None),
485	}
486}
487
488pub(super) async fn provide_selection_ranges(
489	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
490	document_uri:Url,
491	positions:Vec<PositionDTO>,
492) -> Result<Option<Value>, CommonError> {
493	let provider =
494		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::SelectionRange).await?;
495	match provider {
496		Some(registration) => {
497			let response = invoke_provider(
498				environment,
499				&registration,
500				vec![
501					json!(registration.Handle),
502					json!({ "external": document_uri.to_string(), "$mid": 1 }),
503					json!(positions),
504				],
505			)
506			.await?;
507			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
508		},
509		None => Ok(None),
510	}
511}
512
513pub(super) async fn provide_semantic_tokens_full(
514	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
515	document_uri:Url,
516) -> Result<Option<Value>, CommonError> {
517	let provider =
518		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::SemanticTokens).await?;
519	match provider {
520		Some(registration) => {
521			let response = invoke_provider(
522				environment,
523				&registration,
524				vec![
525					json!(registration.Handle),
526					json!({ "external": document_uri.to_string(), "$mid": 1 }),
527				],
528			)
529			.await?;
530			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
531		},
532		None => Ok(None),
533	}
534}
535
536pub(super) async fn provide_inlay_hints(
537	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
538	document_uri:Url,
539	range_dto:Value,
540) -> Result<Option<Value>, CommonError> {
541	let provider =
542		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::InlayHint).await?;
543	match provider {
544		Some(registration) => {
545			let response = invoke_provider(
546				environment,
547				&registration,
548				vec![
549					json!(registration.Handle),
550					json!({ "external": document_uri.to_string(), "$mid": 1 }),
551					range_dto,
552				],
553			)
554			.await?;
555			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
556		},
557		None => Ok(None),
558	}
559}
560
561pub(super) async fn provide_type_hierarchy_supertypes(
562	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
563	item_dto:Value,
564) -> Result<Option<Value>, CommonError> {
565	// Type hierarchy uses the item's URI to find the provider
566	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
567	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
568	let provider =
569		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::TypeHierarchy).await?;
570	match provider {
571		Some(registration) => {
572			let response =
573				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
574			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
575		},
576		None => Ok(None),
577	}
578}
579
580pub(super) async fn provide_type_hierarchy_subtypes(
581	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
582	item_dto:Value,
583) -> Result<Option<Value>, CommonError> {
584	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
585	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
586	let provider =
587		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::TypeHierarchy).await?;
588	match provider {
589		Some(registration) => {
590			let response =
591				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
592			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
593		},
594		None => Ok(None),
595	}
596}
597
598pub(super) async fn provide_call_hierarchy_incoming_calls(
599	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
600	item_dto:Value,
601) -> Result<Option<Value>, CommonError> {
602	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
603	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
604	let provider =
605		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CallHierarchy).await?;
606	match provider {
607		Some(registration) => {
608			let response =
609				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
610			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
611		},
612		None => Ok(None),
613	}
614}
615
616pub(super) async fn provide_call_hierarchy_outgoing_calls(
617	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
618	item_dto:Value,
619) -> Result<Option<Value>, CommonError> {
620	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
621	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
622	let provider =
623		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CallHierarchy).await?;
624	match provider {
625		Some(registration) => {
626			let response =
627				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
628			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
629		},
630		None => Ok(None),
631	}
632}
633
634pub(super) async fn provide_linked_editing_ranges(
635	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
636	document_uri:Url,
637	position_dto:PositionDTO,
638) -> Result<Option<Value>, CommonError> {
639	let provider =
640		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::LinkedEditingRange)
641			.await?;
642	match provider {
643		Some(registration) => {
644			let response = invoke_provider(
645				environment,
646				&registration,
647				vec![
648					json!(registration.Handle),
649					json!({ "external": document_uri.to_string(), "$mid": 1 }),
650					json!(position_dto),
651				],
652			)
653			.await?;
654			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
655		},
656		None => Ok(None),
657	}
658}
659
660pub(super) async fn provide_on_type_formatting_edits(
661	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
662	document_uri:Url,
663	position_dto:PositionDTO,
664	character:String,
665	options_dto:Value,
666) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
667	let provider =
668		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::OnTypeFormatting)
669			.await?;
670	match provider {
671		Some(registration) => {
672			let response = invoke_provider(
673				environment,
674				&registration,
675				vec![
676					json!(registration.Handle),
677					json!({ "external": document_uri.to_string(), "$mid": 1 }),
678					json!(position_dto),
679					json!(character),
680					options_dto,
681				],
682			)
683			.await?;
684			if response.is_null() {
685				Ok(None)
686			} else {
687				serde_json::from_value(response).map_err(|error| {
688					CommonError::SerializationError {
689						Description:format!("Failed to deserialize Vec<TextEditDTO>: {}", error),
690					}
691				})
692			}
693		},
694		None => Ok(None),
695	}
696}
697
698async fn invoke_provider(
699	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
700	registration:&ProviderRegistrationDTO,
701	arguments:Vec<Value>,
702) -> Result<Value, CommonError> {
703	let rpc_method = format!("$provide{}", registration.ProviderType.to_string());
704	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
705	ipc_provider
706		.SendRequestToSideCar(registration.SideCarIdentifier.clone(), rpc_method, json!(arguments), 5000)
707		.await
708}