use glua_code_analysis::{DbIndex, LuaCompilation, SemanticModel};
use lsp_types::{CompletionItem, Documentation, MarkedString, MarkupContent};
use crate::{
context::ClientId,
handlers::hover::{HoverBuilder, build_hover_content_for_completion},
};
use super::{
add_completions::color_preview_documentation,
completion_data::{CompletionColorInfo, CompletionData, CompletionDataType},
};
pub fn resolve_completion(
compilation: &LuaCompilation,
semantic_model: &SemanticModel,
db: &DbIndex,
completion_item: &mut CompletionItem,
completion_data: CompletionData,
client_id: ClientId,
) -> Option<()> {
let color = completion_data.color.clone();
match completion_data.typ {
CompletionDataType::PropertyOwnerId(property_id) => {
let hover_builder =
build_hover_content_for_completion(compilation, semantic_model, db, property_id);
if let Some(mut hover_builder) = hover_builder {
update_function_signature_info(&mut hover_builder, completion_data.overload_count);
if client_id.is_vscode() {
build_vscode_completion_item(completion_item, hover_builder, None);
} else {
build_other_completion_item(completion_item, hover_builder, None);
}
}
}
CompletionDataType::Overload((property_id, index)) => {
let hover_builder =
build_hover_content_for_completion(compilation, semantic_model, db, property_id);
if let Some(mut hover_builder) = hover_builder {
update_function_signature_info(&mut hover_builder, completion_data.overload_count);
if client_id.is_vscode() {
build_vscode_completion_item(completion_item, hover_builder, Some(index));
} else {
build_other_completion_item(completion_item, hover_builder, Some(index));
}
}
}
_ => {}
}
if let Some(color) = color {
apply_color_completion_documentation(completion_item, &color);
}
Some(())
}
pub fn update_function_signature_info(
hover_builder: &mut HoverBuilder,
overload_count: Option<usize>,
) {
if let Some(overload_count) = overload_count
&& overload_count > 0
{
if let Some(signature_overload) = &mut hover_builder.signature_overload {
for signature in signature_overload.iter_mut() {
if let MarkedString::LanguageString(s) = signature {
s.value = format!("{} (+{} overloads)", s.value, overload_count);
}
}
}
if let MarkedString::LanguageString(s) = &mut hover_builder.primary {
s.value = format!("{} (+{} overloads)", s.value, overload_count);
}
}
}
fn build_vscode_completion_item(
completion_item: &mut CompletionItem,
hover_builder: HoverBuilder,
overload_index: Option<usize>,
) -> Option<()> {
let realm_badge = hover_builder.realm_badge_markdown();
let type_description = overload_index
.and_then(|index| {
hover_builder
.signature_overload
.and_then(|overloads| overloads.get(index).cloned())
})
.unwrap_or_else(|| hover_builder.primary.clone());
match type_description {
MarkedString::String(s) => {
completion_item.detail = Some(s);
}
MarkedString::LanguageString(s) => {
completion_item.detail = Some(s.value);
}
}
let documentation = {
let mut result = String::new();
let mut first_line = true;
if let Some(realm_badge) = realm_badge {
result.push_str(&format!("\n{}\n", realm_badge));
}
for description in hover_builder.annotation_description {
match description {
MarkedString::String(s) => {
if first_line && s == "---" {
first_line = false;
} else {
result.push_str(&format!("\n{}\n", s));
}
}
MarkedString::LanguageString(s) => {
result.push_str(&format!("\n```{}\n{}\n```\n", s.language, s.value));
}
}
}
if let Some(type_expansion) = hover_builder.type_expansion {
for type_expansion in type_expansion {
result.push_str(&format!("\n```{}\n{}\n```\n", "lua", type_expansion));
}
}
result.trim_end().to_string()
};
if !documentation.is_empty() {
completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
value: documentation,
}));
}
Some(())
}
fn build_other_completion_item(
completion_item: &mut CompletionItem,
hover_builder: HoverBuilder,
overload_index: Option<usize>,
) -> Option<()> {
let mut result = String::new();
let realm_badge = hover_builder.realm_badge_markdown();
let type_description = overload_index
.and_then(|index| {
hover_builder
.signature_overload
.and_then(|overloads| overloads.get(index).cloned())
})
.unwrap_or_else(|| hover_builder.primary.clone());
match type_description {
MarkedString::String(s) => {
result.push_str(&format!("\n{}\n", s));
}
MarkedString::LanguageString(s) => {
result.push_str(&format!("\n```{}\n{}\n```\n", s.language, s.value));
}
}
if let Some(MarkedString::String(s)) = hover_builder.location_path {
result.push_str(&format!("\n{}\n", s));
}
if let Some(realm_badge) = realm_badge {
result.push_str(&format!("\n{}\n", realm_badge));
}
for marked_string in hover_builder.annotation_description {
match marked_string {
MarkedString::String(s) => {
result.push_str(&format!("\n{}\n", s));
}
MarkedString::LanguageString(s) => {
result.push_str(&format!("\n```{}\n{}\n```\n", s.language, s.value));
}
}
}
if let Some(type_expansion) = hover_builder.type_expansion {
for type_expansion in type_expansion {
result.push_str(&format!("\n```{}\n{}\n```\n", "lua", type_expansion));
}
}
completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
value: result,
}));
Some(())
}
fn apply_color_completion_documentation(
completion_item: &mut CompletionItem,
color: &CompletionColorInfo,
) {
let preview_documentation = color_preview_documentation(color);
match completion_item.documentation.take() {
Some(Documentation::MarkupContent(mut markup)) => {
if !markup.value.contains(&preview_documentation) {
if !markup.value.trim().is_empty() {
markup.value.push_str("\n\n");
}
markup.value.push_str(&preview_documentation);
}
completion_item.documentation = Some(Documentation::MarkupContent(markup));
}
Some(Documentation::String(mut text)) => {
if !text.contains(&preview_documentation) {
if !text.trim().is_empty() {
text.push_str("\n\n");
}
text.push_str(&preview_documentation);
}
completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
value: text,
}));
}
None => {
completion_item.documentation = Some(Documentation::MarkupContent(MarkupContent {
kind: lsp_types::MarkupKind::Markdown,
value: preview_documentation,
}));
}
}
}