Skip to main content

Mountain/RPC/CocoonService/Provider/
ProvideCompletionItems.rs

1
2//! Forward a completion request to the registered provider and project
3//! the suggestions into the gRPC `CompletionItem` shape.
4
5use tonic::{Response, Status};
6use url::Url;
7use CommonLibrary::LanguageFeature::{
8	DTO::{
9		CompletionContextDTO::{CompletionContextDTO, CompletionTriggerKindDTO},
10		PositionDTO::PositionDTO,
11	},
12	LanguageFeatureProviderRegistry::LanguageFeatureProviderRegistry,
13};
14
15use crate::{
16	RPC::CocoonService::CocoonServiceImpl,
17	Vine::Generated::{CompletionItem, ProvideCompletionItemsRequest, ProvideCompletionItemsResponse},
18	dev_log,
19};
20
21pub async fn Fn(
22	Service:&CocoonServiceImpl,
23
24	Request:ProvideCompletionItemsRequest,
25) -> Result<Response<ProvideCompletionItemsResponse>, Status> {
26	dev_log!(
27		"cocoon",
28		"[CocoonService] Providing completions for provider {}",
29		Request.provider_handle
30	);
31
32	let URI = Request.uri.as_ref().map(|U| U.value.as_str()).unwrap_or("");
33
34	let DocumentURI = Url::parse(URI).map_err(|E| Status::invalid_argument(format!("Invalid URI: {}", E)))?;
35
36	let Position_ = Request.position.as_ref();
37
38	let PositionDTO_ = PositionDTO {
39		LineNumber:Position_.map(|P| P.line).unwrap_or(0),
40
41		Column:Position_.map(|P| P.character).unwrap_or(0),
42	};
43
44	let ContextDTO = CompletionContextDTO {
45		TriggerKind:CompletionTriggerKindDTO::Invoke,
46
47		TriggerCharacter:if Request.trigger_character.is_empty() {
48			None
49		} else {
50			Some(Request.trigger_character.clone())
51		},
52	};
53
54	match Service
55		.environment
56		.ProvideCompletions(DocumentURI, PositionDTO_, ContextDTO, None)
57		.await
58	{
59		Ok(Some(List)) => {
60			let Items = List
61				.Suggestions
62				.iter()
63				.map(|S| {
64					CompletionItem {
65						label:S.Label.as_str().map(|L| L.to_string()).unwrap_or_default(),
66						kind:format!("{}", S.Kind),
67						detail:S.Detail.clone().unwrap_or_default(),
68						documentation:Vec::new(),
69						insert_text:S.InsertText.as_ref().and_then(|V| V.as_str()).unwrap_or("").to_string(),
70					}
71				})
72				.collect();
73
74			Ok(Response::new(ProvideCompletionItemsResponse { items:Items }))
75		},
76
77		Ok(None) => Ok(Response::new(ProvideCompletionItemsResponse { items:Vec::new() })),
78
79		Err(Error) => Err(Status::internal(format!("Completions failed: {}", Error))),
80	}
81}