Skip to main content

luaur_analysis/functions/
make_suggestions_from_node.rs

1extern crate alloc;
2
3use crate::records::require_node::RequireNode;
4use crate::records::require_suggestion::RequireSuggestion;
5use crate::type_aliases::require_suggestions::RequireSuggestions;
6use alloc::boxed::Box;
7use alloc::string::{String, ToString};
8use alloc::vec::Vec;
9use luaur_common::macros::luau_assert::LUAU_ASSERT;
10
11pub(crate) fn make_suggestions_from_node(
12    node: Box<dyn RequireNode>,
13    path: &str,
14    is_partial_path: bool,
15) -> RequireSuggestions {
16    LUAU_ASSERT!(!path.is_empty());
17
18    let mut result = RequireSuggestions::new();
19
20    let last_slash_in_path = path.rfind('/');
21
22    if let Some(last_slash) = last_slash_in_path {
23        let mut parent_suggestion = RequireSuggestion {
24            label: "..".to_string(),
25            full_path: String::new(),
26            tags: Vec::new(),
27        };
28
29        if last_slash >= 2 && path.as_bytes().get(last_slash - 2..=last_slash) == Some(b"../") {
30            let mut full_path = path[0..=last_slash].to_string();
31            full_path.push_str("..");
32            parent_suggestion.full_path = full_path;
33        } else {
34            parent_suggestion.full_path = path[0..last_slash].to_string();
35        }
36
37        result.push(parent_suggestion);
38    }
39
40    let mut full_path_prefix = String::new();
41    if is_partial_path {
42        if let Some(last_slash) = last_slash_in_path {
43            full_path_prefix.push_str(&path[0..=last_slash]);
44        }
45    } else {
46        if path.ends_with('/') {
47            full_path_prefix.push_str(path);
48        } else {
49            full_path_prefix.push_str(path);
50            full_path_prefix.push('/');
51        }
52    }
53
54    for child in node.get_children() {
55        let path_component = child.get_path_component();
56
57        if path_component.contains('/') {
58            continue;
59        }
60
61        let label = if is_partial_path || path.ends_with('/') {
62            RequireNode::get_label(&*child)
63        } else {
64            let mut l = "/".to_string();
65            l.push_str(&RequireNode::get_label(&*child));
66            l
67        };
68
69        let mut full_path = full_path_prefix.clone();
70        full_path.push_str(&path_component);
71
72        let tags = RequireNode::get_tags(&*child);
73
74        result.push(RequireSuggestion {
75            label,
76            full_path,
77            tags,
78        });
79    }
80
81    result
82}