Skip to main content

luaur_analyze_cli/records/
cli_file_resolver.rs

1//! Port of `struct CliFileResolver : Luau::FileResolver` (`CLI/src/Analyze.cpp:160-229`).
2//!
3//! A concrete `FileResolver` subclass: `#[repr(C)]` with `base: FileResolver`
4//! first so a `*mut FileResolver` (the vtable receiver) can be cast back to
5//! `*mut CliFileResolver`. The three overridden virtuals (`readSource`,
6//! `resolveModule`, `getHumanReadableModuleName`) are wired to thunks that
7//! delegate to the inherent methods; `getEnvironmentForModule` is not overridden
8//! and uses the base default.
9
10use alloc::string::String;
11use luaur_analysis::records::file_resolver::{FileResolver, FileResolverVtable};
12use luaur_analysis::records::module_info::ModuleInfo;
13use luaur_analysis::records::source_code::SourceCode;
14use luaur_analysis::records::type_check_limits::TypeCheckLimits;
15use luaur_analysis::type_aliases::module_name_file_resolver::ModuleName;
16use luaur_ast::records::ast_expr::AstExpr;
17
18#[repr(C)]
19pub struct CliFileResolver {
20    pub base: FileResolver,
21}
22
23/// `std::optional<SourceCode> readSource(const ModuleName&)` thunk.
24///
25/// # Safety
26/// `this` must point at the `base` subobject of a live `CliFileResolver`.
27pub(crate) unsafe fn cli_file_resolver_read_source_thunk(
28    this: *mut FileResolver,
29    name: &ModuleName,
30) -> Option<SourceCode> {
31    let this = this as *mut CliFileResolver;
32    (*this).read_source(name)
33}
34
35/// `std::optional<ModuleInfo> resolveModule(const ModuleInfo*, AstExpr*, const TypeCheckLimits&)` thunk.
36///
37/// # Safety
38/// `this` must point at the `base` subobject of a live `CliFileResolver`.
39pub(crate) unsafe fn cli_file_resolver_resolve_module_thunk(
40    this: *mut FileResolver,
41    context: *const ModuleInfo,
42    expr: *mut AstExpr,
43    limits: &TypeCheckLimits,
44) -> Option<ModuleInfo> {
45    let this = this as *mut CliFileResolver;
46    (*this).resolve_module(context, expr, limits)
47}
48
49/// `std::string getHumanReadableModuleName(const ModuleName&) const` thunk.
50///
51/// # Safety
52/// `this` must point at the `base` subobject of a live `CliFileResolver`.
53pub(crate) unsafe fn cli_file_resolver_get_human_readable_module_name_thunk(
54    this: *const FileResolver,
55    name: &ModuleName,
56) -> String {
57    let this = this as *const CliFileResolver;
58    crate::methods::cli_file_resolver_get_human_readable_module_name::cli_file_resolver_get_human_readable_module_name(
59        this, name,
60    )
61}
62
63/// `getEnvironmentForModule` is not overridden by `CliFileResolver`; this mirrors
64/// the `FileResolver` base default (`return std::nullopt;`).
65///
66/// # Safety
67/// `this` must point at a live `FileResolver` (the base subobject).
68unsafe fn cli_file_resolver_get_environment_for_module_default(
69    _this: *const FileResolver,
70    _name: &ModuleName,
71) -> Option<String> {
72    None
73}
74
75impl CliFileResolver {
76    pub fn new() -> Self {
77        let vtable = FileResolverVtable {
78            read_source: cli_file_resolver_read_source_thunk,
79            resolve_module: cli_file_resolver_resolve_module_thunk,
80            get_human_readable_module_name: cli_file_resolver_get_human_readable_module_name_thunk,
81            get_environment_for_module: cli_file_resolver_get_environment_for_module_default,
82        };
83
84        CliFileResolver {
85            base: FileResolver {
86                vtable,
87                require_suggester: None,
88            },
89        }
90    }
91}
92
93impl Default for CliFileResolver {
94    fn default() -> Self {
95        Self::new()
96    }
97}