Skip to main content

luaur_analysis/functions/
autocomplete_autocomplete.rs

1//! Generated skeleton item.
2//! Node: `cxx:Function:Luau.Analysis:Analysis/src/Autocomplete.cpp:17:autocomplete`
3//! Source: `Analysis/src/Autocomplete.cpp`
4
5use crate::enums::solver_mode::SolverMode;
6use crate::functions::autocomplete_autocomplete_core::autocomplete_;
7use crate::functions::find_ancestry_at_position_for_autocomplete_ast_query::find_ancestry_at_position_for_autocomplete_source_module_position;
8use crate::functions::find_scope_at_position::find_scope_at_position;
9use crate::functions::is_within_comment_module_alt_b::is_within_comment_source_module_position;
10use crate::functions::is_within_hot_comment_module_alt_b::is_within_hot_comment_source_module_position;
11use crate::records::autocomplete_result::AutocompleteResult;
12use crate::records::frontend::Frontend;
13use crate::records::type_arena::TypeArena;
14use crate::type_aliases::module_name_file_resolver::ModuleName;
15use crate::type_aliases::string_completion_callback::StringCompletionCallback;
16use luaur_ast::records::position::Position;
17use luaur_common::macros::luau_assert::LUAU_ASSERT;
18use luaur_common::macros::luau_timetrace_argument::LUAU_TIMETRACE_ARGUMENT;
19use luaur_common::macros::luau_timetrace_scope::LUAU_TIMETRACE_SCOPE;
20
21pub fn autocomplete(
22    frontend: &mut Frontend,
23    module_name: &ModuleName,
24    position: Position,
25    callback: StringCompletionCallback,
26) -> AutocompleteResult {
27    LUAU_TIMETRACE_SCOPE!("Luau::autocomplete", "Autocomplete");
28    LUAU_TIMETRACE_ARGUMENT!("name", module_name.as_str());
29
30    let source_module = frontend.get_source_module(module_name);
31    if source_module.is_null() {
32        return AutocompleteResult::autocomplete_result();
33    }
34
35    // ModulePtr is modeled as a non-null `Arc<Module>`; C++ `if (!module) return {}`
36    // guards a null shared_ptr, which cannot occur for the non-null Arc here.
37    let module = if frontend.get_luau_solver_mode() == SolverMode::New {
38        frontend.module_resolver.get_module(module_name)
39    } else {
40        frontend
41            .module_resolver_for_autocomplete
42            .get_module(module_name)
43    };
44
45    let builtin_types = unsafe { &*frontend.builtin_types };
46
47    let global_scope = if frontend.get_luau_solver_mode() == SolverMode::New {
48        alloc::sync::Arc::as_ptr(&frontend.globals.global_scope)
49            as *mut crate::records::scope::Scope
50    } else {
51        alloc::sync::Arc::as_ptr(&frontend.globals_for_autocomplete.global_scope)
52            as *mut crate::records::scope::Scope
53    };
54
55    let mut type_arena = TypeArena::default();
56    let is_in_hot_comment =
57        is_within_hot_comment_source_module_position(unsafe { &*source_module }, position);
58    if is_within_comment_source_module_position(unsafe { &*source_module }, position)
59        && !is_in_hot_comment
60    {
61        return AutocompleteResult::autocomplete_result();
62    }
63
64    let mut ancestry = find_ancestry_at_position_for_autocomplete_source_module_position(
65        unsafe { &*source_module },
66        position,
67    );
68    LUAU_ASSERT!(!ancestry.is_empty());
69    // `findScopeAtPosition` returns a (nullable) ScopePtr; modeled here as
70    // `Option<ScopePtr>`. `autocomplete_` takes `&ScopePtr`, so unwrap the
71    // resolved scope (the empty-scopes corner is degenerate).
72    let start_scope = find_scope_at_position(&module, position).unwrap();
73
74    autocomplete_(
75        &module,
76        builtin_types,
77        &mut type_arena,
78        &mut ancestry,
79        global_scope,
80        &start_scope,
81        position,
82        frontend.file_resolver,
83        callback,
84        is_in_hot_comment,
85    )
86}