emmylua_parser/syntax/node/lua/
path_trait.rs

1use crate::LuaAstNode;
2
3use super::{LuaExpr, LuaIndexKey};
4
5pub trait PathTrait: LuaAstNode {
6    fn get_access_path(&self) -> Option<String> {
7        let mut paths = Vec::new();
8        let mut current_node = self.syntax().clone();
9        loop {
10            match LuaExpr::cast(current_node)? {
11                LuaExpr::NameExpr(name_expr) => {
12                    let name = name_expr.get_name_text()?;
13                    if paths.is_empty() {
14                        return Some(name);
15                    } else {
16                        paths.push(name);
17                        paths.reverse();
18                        return Some(paths.join("."));
19                    }
20                }
21                LuaExpr::CallExpr(call_expr) => {
22                    let prefix_expr = call_expr.get_prefix_expr()?;
23                    current_node = prefix_expr.syntax().clone();
24                }
25                LuaExpr::IndexExpr(index_expr) => {
26                    match index_expr.get_index_key()? {
27                        LuaIndexKey::String(s) => {
28                            paths.push(s.get_value());
29                        }
30                        LuaIndexKey::Name(name) => {
31                            paths.push(name.get_name_text().to_string());
32                        }
33                        LuaIndexKey::Integer(i) => {
34                            paths.push(i.get_int_value().to_string());
35                        }
36                        LuaIndexKey::Expr(expr) => {
37                            let text = format!("[{}]", expr.syntax().text());
38                            paths.push(text);
39                        }
40                        LuaIndexKey::Idx(idx) => {
41                            let text = format!("[{}]", idx);
42                            paths.push(text);
43                        }
44                    }
45
46                    current_node = index_expr.get_prefix_expr()?.syntax().clone();
47                }
48                _ => return None,
49            }
50        }
51    }
52
53    fn get_member_path(&self) -> Option<String> {
54        let mut paths = Vec::new();
55        let mut current_node = self.syntax().clone();
56        loop {
57            match LuaExpr::cast(current_node)? {
58                LuaExpr::NameExpr(_) => {
59                    if paths.is_empty() {
60                        return None;
61                    } else {
62                        paths.reverse();
63                        return Some(paths.join("."));
64                    }
65                }
66                LuaExpr::CallExpr(call_expr) => {
67                    let prefix_expr = call_expr.get_prefix_expr()?;
68                    current_node = prefix_expr.syntax().clone();
69                }
70                LuaExpr::IndexExpr(index_expr) => {
71                    let path_parts = index_expr.get_index_key()?.get_path_part();
72                    paths.push(path_parts);
73
74                    current_node = index_expr.get_prefix_expr()?.syntax().clone();
75                }
76                _ => return None,
77            }
78        }
79    }
80}