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
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
707pub(super) async fn provide_call_hierarchy_incoming_calls(
708	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
709
710	item_dto:Value,
711) -> Result<Option<Value>, CommonError> {
712	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
713
714	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
715
716	let provider =
717		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CallHierarchy).await?;
718
719	match provider {
720		Some(registration) => {
721			let response =
722				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
723
724			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
725		},
726
727		None => Ok(None),
728	}
729}
730
731pub(super) async fn provide_call_hierarchy_outgoing_calls(
732	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
733
734	item_dto:Value,
735) -> Result<Option<Value>, CommonError> {
736	let uri_str = item_dto.get("uri").and_then(|u| u.as_str()).unwrap_or("");
737
738	let document_uri = Url::parse(uri_str).unwrap_or_else(|_| Url::parse("file:///unknown").unwrap());
739
740	let provider =
741		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::CallHierarchy).await?;
742
743	match provider {
744		Some(registration) => {
745			let response =
746				invoke_provider(environment, &registration, vec![json!(registration.Handle), item_dto]).await?;
747
748			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
749		},
750
751		None => Ok(None),
752	}
753}
754
755pub(super) async fn provide_linked_editing_ranges(
756	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
757
758	document_uri:Url,
759
760	position_dto:PositionDTO,
761) -> Result<Option<Value>, CommonError> {
762	let provider =
763		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::LinkedEditingRange)
764			.await?;
765
766	match provider {
767		Some(registration) => {
768			let response = invoke_provider(
769				environment,
770				&registration,
771				vec![
772					json!(registration.Handle),
773					json!({ "external": document_uri.to_string(), "$mid": 1 }),
774					json!(position_dto),
775				],
776			)
777			.await?;
778
779			if response.is_null() { Ok(None) } else { Ok(Some(response)) }
780		},
781
782		None => Ok(None),
783	}
784}
785
786pub(super) async fn provide_on_type_formatting_edits(
787	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
788
789	document_uri:Url,
790
791	position_dto:PositionDTO,
792
793	character:String,
794
795	options_dto:Value,
796) -> Result<Option<Vec<TextEditDTO>>, CommonError> {
797	let provider =
798		super::ProviderLookup::get_matching_provider(environment, &document_uri, ProviderType::OnTypeFormatting)
799			.await?;
800
801	match provider {
802		Some(registration) => {
803			let response = invoke_provider(
804				environment,
805				&registration,
806				vec![
807					json!(registration.Handle),
808					json!({ "external": document_uri.to_string(), "$mid": 1 }),
809					json!(position_dto),
810					json!(character),
811					options_dto,
812				],
813			)
814			.await?;
815
816			if response.is_null() {
817				Ok(None)
818			} else {
819				serde_json::from_value(response).map_err(|error| {
820					CommonError::SerializationError {
821						Description:format!("Failed to deserialize Vec<TextEditDTO>: {}", error),
822					}
823				})
824			}
825		},
826
827		None => Ok(None),
828	}
829}
830
831async fn invoke_provider(
832	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
833
834	registration:&ProviderRegistrationDTO,
835
836	arguments:Vec<Value>,
837) -> Result<Value, CommonError> {
838	let rpc_method = format!("$provide{}", registration.ProviderType.to_string());
839
840	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
841
842	ipc_provider
843		.SendRequestToSideCar(registration.SideCarIdentifier.clone(), rpc_method, json!(arguments), 5000)
844		.await
845}