Skip to main content

DevelopmentNodeEnvironment_MicrosoftVSCodeDependency_22NodeVersion_Bundle_Clean_Debug_ElectronProfile_EsbuildCompiler_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
29	document_uri:Url,
30
31	range_or_selection_dto:Value,
32
33	context_dto:Value,
34) -> Result<Option<Value>, CommonError> {
35	let provider =
36		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CodeAction).await?;
37
38	match provider {
39		Some(registration) => {
40			let response = invoke_provider(
41				environment,
42				&registration,
43				vec![
44					json!(registration.Handle),
45					json!({ "external": document_uri.to_string(), "$mid": 1 }),
46					range_or_selection_dto,
47					context_dto,
48				],
49			)
50			.await?;
51
52			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
53		},
54
55		None => Ok(None),
56	}
57}
58
59pub(super) async fn provide_code_lenses(
60	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
61
62	document_uri:Url,
63) -> Result<Option<Value>, CommonError> {
64	let provider =
65		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CodeLens).await?;
66
67	match provider {
68		Some(registration) => {
69			let response = invoke_provider(
70				environment,
71				&registration,
72				vec![
73					json!(registration.Handle),
74					json!({ "external": document_uri.to_string(), "$mid": 1 }),
75				],
76			)
77			.await?;
78
79			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
80		},
81
82		None => Ok(None),
83	}
84}
85
86pub(super) async fn provide_completions(
87	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
88
89	document_uri:Url,
90
91	position_dto:PositionDTO,
92
93	context_dto:CompletionContextDTO,
94
95	cancellation_token_value:Option<Value>,
96) -> Result<Option<CompletionListDTO>, CommonError> {
97	let provider =
98		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Completion).await?;
99
100	match provider {
101		Some(registration) => {
102			let response = invoke_provider(
103				environment,
104				&registration,
105				vec![
106					json!(registration.Handle),
107					json!({ "external": document_uri.to_string(), "$mid": 1 }),
108					json!(position_dto),
109					json!(context_dto),
110					cancellation_token_value.unwrap_or_else(|| json!(null)),
111				],
112			)
113			.await?;
114
115			if response.is_null() {
116				Ok(None)
117			} else {
118				serde_json::from_value(response).map_err(|error| {
119					CommonError::SerializationError {
120						Description:format!("Failed to deserialize CompletionListDTO: {}", error),
121					}
122				})
123			}
124		},
125
126		None => Ok(None),
127	}
128}
129
130pub(super) async fn provide_definition(
131	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
132
133	document_uri:Url,
134
135	position_dto:PositionDTO,
136) -> Result<Option<Vec<LocationDTO>>, CommonError> {
137	let provider =
138		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Definition).await?;
139
140	match provider {
141		Some(registration) => {
142			let response = invoke_provider(
143				environment,
144				&registration,
145				vec![
146					json!(registration.Handle),
147					json!({ "external": document_uri.to_string(), "$mid": 1 }),
148					json!(position_dto),
149				],
150			)
151			.await?;
152
153			if response.is_null() {
154				Ok(None)
155			} else {
156				serde_json::from_value(response).map_err(|error| {
157					CommonError::SerializationError {
158						Description:format!("Failed to deserialize Vec<LocationDTO>: {}", error),
159					}
160				})
161			}
162		},
163
164		None => Ok(None),
165	}
166}
167
168pub(super) async fn provide_document_formatting_edits(
169	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
170
171	document_uri:Url,
172
173	options_dto:Value,
174) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
175	let provider =
176		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentFormatting)
177			.await?;
178
179	match provider {
180		Some(registration) => {
181			let response = invoke_provider(
182				environment,
183				&registration,
184				vec![
185					json!(registration.Handle),
186					json!({ "external": document_uri.to_string(), "$mid": 1 }),
187					options_dto,
188				],
189			)
190			.await?;
191
192			if response.is_null() {
193				Ok(None)
194			} else {
195				serde_json::from_value(response).map_err(|error| {
196					CommonError::SerializationError {
197						Description:format!("Failed to deserialize Vec<TextEditDTO>: {}", error),
198					}
199				})
200			}
201		},
202
203		None => Ok(None),
204	}
205}
206
207pub(super) async fn provide_document_highlights(
208	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
209
210	document_uri:Url,
211
212	position_dto:PositionDTO,
213) -> Result<Option<Value>, CommonError> {
214	let provider =
215		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentHighlight)
216			.await?;
217
218	match provider {
219		Some(registration) => {
220			let response = invoke_provider(
221				environment,
222				&registration,
223				vec![
224					json!(registration.Handle),
225					json!({ "external": document_uri.to_string(), "$mid": 1 }),
226					json!(position_dto),
227				],
228			)
229			.await?;
230
231			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
232		},
233
234		None => Ok(None),
235	}
236}
237
238pub(super) async fn provide_document_links(
239	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
240
241	document_uri:Url,
242) -> Result<Option<Value>, CommonError> {
243	let provider =
244		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentLink).await?;
245
246	match provider {
247		Some(registration) => {
248			let response = invoke_provider(
249				environment,
250				&registration,
251				vec![
252					json!(registration.Handle),
253					json!({ "external": document_uri.to_string(), "$mid": 1 }),
254				],
255			)
256			.await?;
257
258			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
259		},
260
261		None => Ok(None),
262	}
263}
264
265pub(super) async fn provide_document_range_formatting_edits(
266	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
267
268	document_uri:Url,
269
270	range_dto:Value,
271
272	options_dto:Value,
273) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
274	let provider =
275		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentRangeFormatting)
276			.await?;
277
278	match provider {
279		Some(registration) => {
280			let response = invoke_provider(
281				environment,
282				&registration,
283				vec![
284					json!(registration.Handle),
285					json!({ "external": document_uri.to_string(), "$mid": 1 }),
286					range_dto,
287					options_dto,
288				],
289			)
290			.await?;
291
292			if response.is_null() {
293				Ok(None)
294			} else {
295				serde_json::from_value(response).map_err(|error| {
296					CommonError::SerializationError {
297						Description:format!("Failed to deserialize Vec<TextEditDTO>: {}", error),
298					}
299				})
300			}
301		},
302
303		None => Ok(None),
304	}
305}
306
307pub(super) async fn provide_hover(
308	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
309
310	document_uri:Url,
311
312	position_dto:PositionDTO,
313) -> Result<Option<HoverResultDTO>, CommonError> {
314	let provider =
315		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Hover).await?;
316
317	match provider {
318		Some(registration) => {
319			let response = invoke_provider(
320				environment,
321				&registration,
322				vec![
323					json!(registration.Handle),
324					json!({ "external": document_uri.to_string(), "$mid": 1 }),
325					json!(position_dto),
326				],
327			)
328			.await?;
329
330			if response.is_null() {
331				Ok(None)
332			} else {
333				serde_json::from_value(response).map_err(|error| {
334					CommonError::SerializationError {
335						Description:format!("Failed to deserialize HoverResultDTO: {}", error),
336					}
337				})
338			}
339		},
340
341		None => Ok(None),
342	}
343}
344
345pub(super) async fn provide_references(
346	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
347
348	document_uri:Url,
349
350	position_dto:PositionDTO,
351
352	context_dto:Value,
353) -> Result<Option<Vec<LocationDTO>>, CommonError> {
354	let provider =
355		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::References).await?;
356
357	match provider {
358		Some(registration) => {
359			let response = invoke_provider(
360				environment,
361				&registration,
362				vec![
363					json!(registration.Handle),
364					json!({ "external": document_uri.to_string(), "$mid": 1 }),
365					json!(position_dto),
366					context_dto,
367				],
368			)
369			.await?;
370
371			if response.is_null() {
372				Ok(None)
373			} else {
374				serde_json::from_value(response).map_err(|error| {
375					CommonError::SerializationError {
376						Description:format!("Failed to deserialize Vec<LocationDTO>: {}", error),
377					}
378				})
379			}
380		},
381
382		None => Ok(None),
383	}
384}
385
386pub(super) async fn prepare_rename(
387	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
388
389	document_uri:Url,
390
391	position_dto:PositionDTO,
392) -> Result<Option<Value>, CommonError> {
393	let provider =
394		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Rename).await?;
395
396	match provider {
397		Some(registration) => {
398			let response = invoke_provider(
399				environment,
400				&registration,
401				vec![
402					json!(registration.Handle),
403					json!({ "external": document_uri.to_string(), "$mid": 1 }),
404					json!(position_dto),
405				],
406			)
407			.await?;
408
409			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
410		},
411
412		None => Ok(None),
413	}
414}
415
416pub(super) async fn provide_rename_edits(
417	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
418
419	document_uri:Url,
420
421	position_dto:PositionDTO,
422
423	new_name:String,
424) -> Result<Option<Value>, CommonError> {
425	let provider =
426		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::Rename).await?;
427
428	match provider {
429		Some(registration) => {
430			let response = invoke_provider(
431				environment,
432				&registration,
433				vec![
434					json!(registration.Handle),
435					json!({ "external": document_uri.to_string(), "$mid": 1 }),
436					json!(position_dto),
437					json!(new_name),
438				],
439			)
440			.await?;
441
442			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
443		},
444
445		None => Ok(None),
446	}
447}
448
449pub(super) async fn provide_document_symbols(
450	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
451
452	document_uri:Url,
453) -> Result<Option<Value>, CommonError> {
454	let provider =
455		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::DocumentSymbol).await?;
456
457	match provider {
458		Some(registration) => {
459			let response = invoke_provider(
460				environment,
461				&registration,
462				vec![
463					json!(registration.Handle),
464					json!({ "external": document_uri.to_string(), "$mid": 1 }),
465				],
466			)
467			.await?;
468
469			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
470		},
471
472		None => Ok(None),
473	}
474}
475
476pub(super) async fn provide_workspace_symbols(
477	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
478
479	query:String,
480) -> Result<Option<Value>, CommonError> {
481	// Workspace symbols don't have a specific document URI - use a dummy lookup.
482	// The provider is registered globally, so we pick the first WorkspaceSymbol
483	// provider.
484	let MatchingRegistration = {
485		let providers = environment
486			.ApplicationState
487			.Extension
488			.ProviderRegistration
489			.LanguageProviders
490			.lock()
491			.map_err(crate::Environment::Utility::ErrorMapping::MapApplicationStateLockErrorToCommonError)?;
492
493		providers
494			.values()
495			.find(|p| p.ProviderType == ProviderType::WorkspaceSymbol)
496			.cloned()
497	};
498
499	match MatchingRegistration {
500		Some(registration) => {
501			let response =
502				invoke_provider(environment, &registration, vec![json!(registration.Handle), json!(query)]).await?;
503
504			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
505		},
506
507		None => Ok(None),
508	}
509}
510
511pub(super) async fn provide_signature_help(
512	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
513
514	document_uri:Url,
515
516	position_dto:PositionDTO,
517
518	context_dto:Value,
519) -> Result<Option<Value>, CommonError> {
520	let provider =
521		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::SignatureHelp).await?;
522
523	match provider {
524		Some(registration) => {
525			let response = invoke_provider(
526				environment,
527				&registration,
528				vec![
529					json!(registration.Handle),
530					json!({ "external": document_uri.to_string(), "$mid": 1 }),
531					json!(position_dto),
532					context_dto,
533				],
534			)
535			.await?;
536
537			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
538		},
539
540		None => Ok(None),
541	}
542}
543
544pub(super) async fn provide_folding_ranges(
545	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
546
547	document_uri:Url,
548) -> Result<Option<Value>, CommonError> {
549	let provider =
550		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::FoldingRange).await?;
551
552	match provider {
553		Some(registration) => {
554			let response = invoke_provider(
555				environment,
556				&registration,
557				vec![
558					json!(registration.Handle),
559					json!({ "external": document_uri.to_string(), "$mid": 1 }),
560				],
561			)
562			.await?;
563
564			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
565		},
566
567		None => Ok(None),
568	}
569}
570
571pub(super) async fn provide_selection_ranges(
572	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
573
574	document_uri:Url,
575
576	positions:Vec<PositionDTO>,
577) -> Result<Option<Value>, CommonError> {
578	let provider =
579		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::SelectionRange).await?;
580
581	match provider {
582		Some(registration) => {
583			let response = invoke_provider(
584				environment,
585				&registration,
586				vec![
587					json!(registration.Handle),
588					json!({ "external": document_uri.to_string(), "$mid": 1 }),
589					json!(positions),
590				],
591			)
592			.await?;
593
594			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
595		},
596
597		None => Ok(None),
598	}
599}
600
601pub(super) async fn provide_semantic_tokens_full(
602	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
603
604	document_uri:Url,
605) -> Result<Option<Value>, CommonError> {
606	let provider =
607		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::SemanticTokens).await?;
608
609	match provider {
610		Some(registration) => {
611			let response = invoke_provider(
612				environment,
613				&registration,
614				vec![
615					json!(registration.Handle),
616					json!({ "external": document_uri.to_string(), "$mid": 1 }),
617				],
618			)
619			.await?;
620
621			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
622		},
623
624		None => Ok(None),
625	}
626}
627
628pub(super) async fn provide_inlay_hints(
629	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
630
631	document_uri:Url,
632
633	range_dto:Value,
634) -> Result<Option<Value>, CommonError> {
635	let provider =
636		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::InlayHint).await?;
637
638	match provider {
639		Some(registration) => {
640			let response = invoke_provider(
641				environment,
642				&registration,
643				vec![
644					json!(registration.Handle),
645					json!({ "external": document_uri.to_string(), "$mid": 1 }),
646					range_dto,
647				],
648			)
649			.await?;
650
651			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
652		},
653
654		None => Ok(None),
655	}
656}
657
658pub(super) async fn provide_type_hierarchy_supertypes(
659	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
660
661	item_dto:Value,
662) -> Result<Option<Value>, CommonError> {
663	// Type hierarchy uses the item's URI to find the provider
664	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
665
666	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
667
668	let provider =
669		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::TypeHierarchy).await?;
670
671	match provider {
672		Some(registration) => {
673			let response =
674				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
675
676			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
677		},
678
679		None => Ok(None),
680	}
681}
682
683pub(super) async fn provide_type_hierarchy_subtypes(
684	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
685
686	item_dto:Value,
687) -> Result<Option<Value>, CommonError> {
688	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
689
690	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
691
692	let provider =
693		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::TypeHierarchy).await?;
694
695	match provider {
696		Some(registration) => {
697			let response =
698				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
699
700			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
701		},
702
703		None => Ok(None),
704	}
705}
706
707/// Prepare call hierarchy - establish the root `CallHierarchyItem` at the
708/// given document position. Extensions implement `prepareCallHierarchy(doc,
709/// pos, token)`. Without this step the incoming/outgoing calls views are always
710/// empty.
711pub(super) async fn prepare_call_hierarchy(
712	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
713
714	document_uri:Url,
715
716	position_dto:PositionDTO,
717) -> Result<Option<Value>, CommonError> {
718	let provider =
719		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CallHierarchy).await?;
720
721	match provider {
722		Some(registration) => {
723			let uri_json = json!({ "external": document_uri.to_string(), "$mid": 1 });
724			let pos_json = json!({ "Line": position_dto.LineNumber, "Character": position_dto.Column });
725			let response = invoke_provider_method(
726				environment,
727				&registration,
728				"$prepareCallHierarchyItems",
729				vec![json!(registration.Handle), uri_json, pos_json],
730			)
731			.await?;
732
733			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
734		},
735
736		None => Ok(None),
737	}
738}
739
740/// Prepare type hierarchy - establish the root `TypeHierarchyItem`.
741pub(super) async fn prepare_type_hierarchy(
742	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
743
744	document_uri:Url,
745
746	position_dto:PositionDTO,
747) -> Result<Option<Value>, CommonError> {
748	let provider =
749		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::TypeHierarchy).await?;
750
751	match provider {
752		Some(registration) => {
753			let uri_json = json!({ "external": document_uri.to_string(), "$mid": 1 });
754			let pos_json = json!({ "Line": position_dto.LineNumber, "Character": position_dto.Column });
755			let response = invoke_provider_method(
756				environment,
757				&registration,
758				"$prepareTypeHierarchyItems",
759				vec![json!(registration.Handle), uri_json, pos_json],
760			)
761			.await?;
762
763			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
764		},
765
766		None => Ok(None),
767	}
768}
769
770pub(super) async fn provide_call_hierarchy_incoming_calls(
771	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
772
773	item_dto:Value,
774) -> Result<Option<Value>, CommonError> {
775	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
776
777	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
778
779	let provider =
780		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CallHierarchy).await?;
781
782	match provider {
783		Some(registration) => {
784			let response =
785				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
786
787			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
788		},
789
790		None => Ok(None),
791	}
792}
793
794pub(super) async fn provide_call_hierarchy_outgoing_calls(
795	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
796
797	item_dto:Value,
798) -> Result<Option<Value>, CommonError> {
799	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
800
801	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
802
803	let provider =
804		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CallHierarchy).await?;
805
806	match provider {
807		Some(registration) => {
808			let response =
809				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
810
811			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
812		},
813
814		None => Ok(None),
815	}
816}
817
818pub(super) async fn provide_linked_editing_ranges(
819	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
820
821	document_uri:Url,
822
823	position_dto:PositionDTO,
824) -> Result<Option<Value>, CommonError> {
825	let provider =
826		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::LinkedEditingRange)
827			.await?;
828
829	match provider {
830		Some(registration) => {
831			let response = invoke_provider(
832				environment,
833				&registration,
834				vec![
835					json!(registration.Handle),
836					json!({ "external": document_uri.to_string(), "$mid": 1 }),
837					json!(position_dto),
838				],
839			)
840			.await?;
841
842			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
843		},
844
845		None => Ok(None),
846	}
847}
848
849pub(super) async fn provide_on_type_formatting_edits(
850	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
851
852	document_uri:Url,
853
854	position_dto:PositionDTO,
855
856	character:String,
857
858	options_dto:Value,
859) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
860	let provider =
861		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::OnTypeFormatting)
862			.await?;
863
864	match provider {
865		Some(registration) => {
866			let response = invoke_provider(
867				environment,
868				&registration,
869				vec![
870					json!(registration.Handle),
871					json!({ "external": document_uri.to_string(), "$mid": 1 }),
872					json!(position_dto),
873					json!(character),
874					options_dto,
875				],
876			)
877			.await?;
878
879			if response.is_null() {
880				Ok(None)
881			} else {
882				serde_json::from_value(response).map_err(|error| {
883					CommonError::SerializationError {
884						Description:format!("Failed to deserialize Vec<TextEditDTO>: {}", error),
885					}
886				})
887			}
888		},
889
890		None => Ok(None),
891	}
892}
893
894async fn invoke_provider(
895	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
896
897	registration:&ProviderRegistrationDTO,
898
899	arguments:Vec<Value>,
900) -> Result<Value, CommonError> {
901	let rpc_method = format!("$provide{}", registration.ProviderType.to_string());
902
903	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
904
905	ipc_provider
906		.SendRequestToSideCar(registration.SideCarIdentifier.clone(), rpc_method, json!(arguments), 5000)
907		.await
908}
909
910/// Like `invoke_provider` but uses an explicit method name instead of
911/// the `$provide{ProviderType}` convention. Used for prepare steps
912/// (`$prepareCallHierarchyItems`, `$prepareTypeHierarchyItems`) where
913/// the method prefix differs from the provider type string.
914async fn invoke_provider_method(
915	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
916
917	registration:&ProviderRegistrationDTO,
918
919	method:&str,
920
921	arguments:Vec<Value>,
922) -> Result<Value, CommonError> {
923	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
924
925	ipc_provider
926		.SendRequestToSideCar(
927			registration.SideCarIdentifier.clone(),
928			method.to_string(),
929			json!(arguments),
930			5000,
931		)
932		.await
933}