#[cfg(test)]
mod tests {
use crate::{
context::ClientId,
handlers::{
completion::{completion, completion_resolve},
test_lib::{ProviderVirtualWorkspace, VirtualCompletionResolveItem, check},
},
};
use googletest::prelude::*;
use lsp_types::{CompletionResponse, CompletionTriggerKind};
use tokio_util::sync::CancellationToken;
#[gtest]
fn test_1() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
check!(ws.check_completion_resolve(
r#"
---@overload fun(event: "AAA", callback: fun(trg: string, data: number)): number
---@overload fun(event: "BBB", callback: fun(trg: string, data: string)): string
---@param event string
---@param callback fun(trg: string, data: number)
---@return number
local function test(event, callback)
if event == "" then
end
end
test<??>
"#,
VirtualCompletionResolveItem {
detail:
"local function test(event: string, callback: fun(trg: string, data: number)) -> number (+2 overloads)"
.to_string(),
documentation: None,
},
));
Ok(())
}
#[gtest]
fn test_2() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
check!(ws.check_completion_resolve(
r#"
---@class Hover.Test2
---@field event fun(event: "游戏-初始化")
---@field event fun(event: "游戏-恢复", key: string)
local Test2 = {}
Test2.<??>
"#,
VirtualCompletionResolveItem {
detail: "(field) Test2.event(event: \"游戏-初始化\") (+1 overloads)".to_string(),
documentation: None,
},
));
Ok(())
}
#[gtest]
fn test_global_path_completion_resolve_preserves_function_union_overloads() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
ws.def(
r#"
ix = ix or {}
ix.character = ix.character or {}
---@type (fun(kind: "steamid"): string) | (fun(kind: "id"): number)
ix.character.lookup = nil
"#,
);
let (content, position) = ProviderVirtualWorkspace::handle_file_content(
r#"
ix = ix or {}
ix.character = ix.character or {}
ix.character.lo<??>
"#,
)?;
let file_id = ws.def(&content);
let result = completion(
&ws.analysis,
file_id,
position,
CompletionTriggerKind::INVOKED,
CancellationToken::new(),
)
.ok_or("failed to get completion")
.or_fail()?;
let items = match result {
CompletionResponse::Array(items) => items,
CompletionResponse::List(list) => list.items,
};
let item = items
.into_iter()
.find(|item| item.label == "lookup")
.ok_or("missing lookup completion")
.or_fail()?;
let item = completion_resolve(&ws.analysis, item, ClientId::VSCode);
let detail = item.detail.ok_or("item detail is empty").or_fail()?;
verify_eq!(
detail,
"function lookup(kind: \"steamid\") -> string (+1 overloads)"
)?;
verify_that!(item.documentation, none())?;
Ok(())
}
#[gtest]
fn test_table_field_function_1() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
check!(ws.check_completion_resolve(
r#"
---@class T
---@field func fun(self:string) 注释注释
---@type T
local t = {
<??>
}
"#,
VirtualCompletionResolveItem {
detail: "(field) T.func(self: string)".to_string(),
documentation: Some("\n注释注释".to_string()),
},
));
Ok(())
}
#[gtest]
fn test_table_field_function_2() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
check!(ws.check_completion_resolve(
r#"
---@class T
---@field func fun(self: T) 注释注释
---@type T
local t = {
<??>
}
"#,
VirtualCompletionResolveItem {
detail: "(method) T:func()".to_string(),
documentation: Some("\n注释注释".to_string()),
},
));
Ok(())
}
#[gtest]
fn test_intersection() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
ws.def(
r#"
---@class Matchers
---@field toBe fun(self: Assertion, expected: any) -- 测试
---@class Inverse<T>
---@field not_ T
---@class Assertion<T>: Matchers<T>
"#,
);
check!(ws.check_completion_resolve(
r#"
---@type Assertion<any>
local expect
expect:<??>
"#,
VirtualCompletionResolveItem {
detail: "(method) Matchers:toBe(expected: any)".to_string(),
documentation: Some("\n测试".to_string()),
},
));
Ok(())
}
#[gtest]
fn test_gmod_sandbox_completion_prefers_annotation_docs() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
let mut emmyrc = ws.get_emmyrc();
emmyrc.gmod.enabled = true;
ws.update_emmyrc(emmyrc);
ws.def_file(
"library/lua/includes/extensions/sandbox_hooks.lua",
r#"
---@class GM
---@type GM
GM = GM or {}
---@class SANDBOX
---@type SANDBOX
SANDBOX = SANDBOX or {}
---Called when a player attempts to spawn a SENT.
function SANDBOX:PlayerSpawnSENT(ply, class)
end
"#,
);
check!(ws.check_completion_resolve(
r#"
function GM:PlayerSpawnSENT(ply, class_name)
end
function SANDBOX:<??>
end
"#,
VirtualCompletionResolveItem {
detail: "(method) SANDBOX:PlayerSpawnSENT(ply, class) (+1 overloads)".to_string(),
documentation: Some(
"\n\n\nCalled when a player attempts to spawn a SENT."
.to_string(),
),
},
));
Ok(())
}
#[gtest]
fn test_gmod_completion_shows_realm_badge_without_description() -> Result<()> {
let mut ws = ProviderVirtualWorkspace::new();
let mut emmyrc = ws.get_emmyrc();
emmyrc.gmod.enabled = true;
ws.update_emmyrc(emmyrc);
ws.def_file(
"library/lua/includes/extensions/sandbox_hooks.lua",
r#"
---@class SANDBOX
---@type SANDBOX
SANDBOX = SANDBOX or {}
function SANDBOX:PlayerSpawnSENT(ply, class)
end
"#,
);
check!(ws.check_completion_resolve(
r#"
function SANDBOX:<??>
end
"#,
VirtualCompletionResolveItem {
detail: "(method) SANDBOX:PlayerSpawnSENT(ply, class)".to_string(),
documentation: Some(
"\n"
.to_string(),
),
},
));
Ok(())
}
}