Skip to content

Commit 4bd67b0

Browse files
committed
refactor document_symbol
1 parent 1e46b13 commit 4bd67b0

File tree

5 files changed

+498
-110
lines changed

5 files changed

+498
-110
lines changed

crates/emmylua_ls/src/handlers/document_symbol/builder.rs

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,25 +45,48 @@ impl<'a> DocumentSymbolBuilder<'a> {
4545
.clone()
4646
}
4747

48-
pub fn add_node_symbol(&mut self, node: LuaSyntaxNode, symbol: LuaSymbol) {
48+
pub fn add_node_symbol(
49+
&mut self,
50+
node: LuaSyntaxNode,
51+
symbol: LuaSymbol,
52+
parent: Option<LuaSyntaxId>,
53+
) -> LuaSyntaxId {
4954
let syntax_id = LuaSyntaxId::new(node.kind(), node.text_range());
5055
self.document_symbols.insert(syntax_id, Box::new(symbol));
51-
let mut node = node;
52-
while let Some(parent) = node.parent() {
53-
let parent_syntax_id = LuaSyntaxId::new(parent.kind(), parent.text_range());
54-
if let Some(symbol) = self.document_symbols.get_mut(&parent_syntax_id) {
55-
symbol.add_child(syntax_id);
56+
57+
if let Some(parent_id) = parent {
58+
self.link_parent_child(parent_id, syntax_id);
59+
return syntax_id;
60+
}
61+
62+
let mut current = node;
63+
while let Some(parent_node) = current.parent() {
64+
let parent_syntax_id = LuaSyntaxId::new(parent_node.kind(), parent_node.text_range());
65+
if let Some(parent_symbol) = self.document_symbols.get_mut(&parent_syntax_id) {
66+
parent_symbol.add_child(syntax_id);
5667
break;
5768
}
5869

59-
node = parent;
70+
current = parent_node;
6071
}
72+
73+
syntax_id
6174
}
6275

63-
pub fn add_token_symbol(&mut self, token: LuaSyntaxToken, symbol: LuaSymbol) {
76+
pub fn add_token_symbol(
77+
&mut self,
78+
token: LuaSyntaxToken,
79+
symbol: LuaSymbol,
80+
parent: Option<LuaSyntaxId>,
81+
) -> LuaSyntaxId {
6482
let syntax_id = LuaSyntaxId::new(token.kind(), token.text_range());
6583
self.document_symbols.insert(syntax_id, Box::new(symbol));
6684

85+
if let Some(parent_id) = parent {
86+
self.link_parent_child(parent_id, syntax_id);
87+
return syntax_id;
88+
}
89+
6790
let mut node = token.parent();
6891
while let Some(parent_node) = node {
6992
let parent_syntax_id = LuaSyntaxId::new(parent_node.kind(), parent_node.text_range());
@@ -74,6 +97,27 @@ impl<'a> DocumentSymbolBuilder<'a> {
7497

7598
node = parent_node.parent();
7699
}
100+
101+
syntax_id
102+
}
103+
104+
pub fn contains_symbol(&self, id: &LuaSyntaxId) -> bool {
105+
self.document_symbols.contains_key(id)
106+
}
107+
108+
pub fn with_symbol_mut<F>(&mut self, id: &LuaSyntaxId, func: F) -> Option<()>
109+
where
110+
F: FnOnce(&mut LuaSymbol),
111+
{
112+
let symbol = self.document_symbols.get_mut(id)?;
113+
func(symbol);
114+
Some(())
115+
}
116+
117+
fn link_parent_child(&mut self, parent: LuaSyntaxId, child: LuaSyntaxId) {
118+
if let Some(parent_symbol) = self.document_symbols.get_mut(&parent) {
119+
parent_symbol.add_child(child);
120+
}
77121
}
78122

79123
#[allow(deprecated)]
@@ -241,4 +285,12 @@ impl LuaSymbol {
241285
pub fn add_child(&mut self, child: LuaSyntaxId) {
242286
self.children.push(child);
243287
}
288+
289+
pub fn set_kind(&mut self, kind: SymbolKind) {
290+
self.kind = kind;
291+
}
292+
293+
pub fn set_detail(&mut self, detail: Option<String>) {
294+
self.detail = detail;
295+
}
244296
}

crates/emmylua_ls/src/handlers/document_symbol/comment.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use emmylua_parser::{LuaAstNode, LuaComment, LuaTokenKind};
1+
use emmylua_parser::{LuaAstNode, LuaComment, LuaSyntaxId, LuaTokenKind};
22
use lsp_types::SymbolKind;
33
use rowan::NodeOrToken;
44

@@ -7,7 +7,8 @@ use super::builder::{DocumentSymbolBuilder, LuaSymbol};
77
pub fn build_doc_region_symbol(
88
builder: &mut DocumentSymbolBuilder,
99
comment: LuaComment,
10-
) -> Option<()> {
10+
parent_id: LuaSyntaxId,
11+
) -> Option<LuaSyntaxId> {
1112
let mut region_token = None;
1213
for child in comment.syntax().children_with_tokens() {
1314
if let NodeOrToken::Token(token) = child {
@@ -18,10 +19,7 @@ pub fn build_doc_region_symbol(
1819
}
1920
}
2021

21-
let region_token = match region_token {
22-
Some(token) => token,
23-
None => return Some(()),
24-
};
22+
let region_token = region_token?;
2523

2624
let description = comment
2725
.get_description()
@@ -46,7 +44,7 @@ pub fn build_doc_region_symbol(
4644
selection_range,
4745
);
4846

49-
builder.add_node_symbol(comment.syntax().clone(), symbol);
47+
let symbol_id = builder.add_node_symbol(comment.syntax().clone(), symbol, Some(parent_id));
5048

51-
Some(())
49+
Some(symbol_id)
5250
}
Lines changed: 72 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,71 @@
11
use emmylua_code_analysis::LuaDeclId;
2-
use emmylua_parser::{LuaAstNode, LuaClosureExpr, LuaIndexKey, LuaSyntaxKind, LuaTableExpr};
2+
use emmylua_parser::{
3+
LuaAstNode, LuaClosureExpr, LuaIndexKey, LuaSyntaxId, LuaSyntaxKind, LuaTableExpr,
4+
};
35
use lsp_types::SymbolKind;
46

57
use super::builder::{DocumentSymbolBuilder, LuaSymbol};
68

79
pub fn build_closure_expr_symbol(
810
builder: &mut DocumentSymbolBuilder,
911
closure: LuaClosureExpr,
10-
) -> Option<()> {
11-
let parent = closure.syntax().parent()?;
12-
if !matches!(
13-
parent.kind().into(),
14-
LuaSyntaxKind::LocalFuncStat | LuaSyntaxKind::FuncStat
15-
) {
12+
parent_id: LuaSyntaxId,
13+
) -> Option<LuaSyntaxId> {
14+
let parent_kind = closure.syntax().parent().map(|parent| parent.kind().into());
15+
let convert_parent_to_function = matches!(
16+
parent_kind,
17+
Some(LuaSyntaxKind::TableFieldAssign | LuaSyntaxKind::TableFieldValue)
18+
);
19+
let needs_own_symbol = match parent_kind {
20+
Some(LuaSyntaxKind::LocalFuncStat | LuaSyntaxKind::FuncStat) => false,
21+
Some(_) if convert_parent_to_function => false,
22+
_ => true,
23+
};
24+
25+
let param_list = closure.get_params_list()?;
26+
let params: Vec<_> = param_list.get_params().collect();
27+
let detail_text = format!(
28+
"({})",
29+
params
30+
.iter()
31+
.map(|param| {
32+
if param.is_dots() {
33+
"...".to_string()
34+
} else {
35+
param
36+
.get_name_token()
37+
.map(|token| token.get_name_text().to_string())
38+
.unwrap_or_default()
39+
}
40+
})
41+
.filter(|name| !name.is_empty())
42+
.collect::<Vec<_>>()
43+
.join(", ")
44+
);
45+
let detail = Some(detail_text.clone());
46+
47+
let mut effective_parent = parent_id;
48+
49+
if needs_own_symbol {
1650
let symbol = LuaSymbol::new(
1751
"closure".to_string(),
18-
None,
52+
detail.clone(),
1953
SymbolKind::MODULE,
2054
closure.get_range(),
2155
);
2256

23-
builder.add_node_symbol(closure.syntax().clone(), symbol);
57+
effective_parent =
58+
builder.add_node_symbol(closure.syntax().clone(), symbol, Some(parent_id));
59+
} else if convert_parent_to_function {
60+
let detail_clone = detail.clone();
61+
builder.with_symbol_mut(&parent_id, |symbol| {
62+
symbol.set_kind(SymbolKind::FUNCTION);
63+
symbol.set_detail(detail_clone);
64+
})?;
2465
}
2566

2667
let file_id = builder.get_file_id();
27-
let param_list = closure.get_params_list()?;
28-
for param in param_list.get_params() {
68+
for param in params {
2969
let decl_id = LuaDeclId::new(file_id, param.get_position());
3070
let decl = builder.get_decl(&decl_id)?;
3171
let typ = builder.get_type(decl_id.into());
@@ -37,21 +77,30 @@ pub fn build_closure_expr_symbol(
3777
decl.get_range(),
3878
);
3979

40-
builder.add_node_symbol(param.syntax().clone(), symbol);
80+
builder.add_node_symbol(param.syntax().clone(), symbol, Some(effective_parent));
4181
}
4282

43-
Some(())
83+
Some(effective_parent)
4484
}
4585

46-
pub fn build_table_symbol(builder: &mut DocumentSymbolBuilder, table: LuaTableExpr) -> Option<()> {
47-
let symbol = LuaSymbol::new(
48-
"table".to_string(),
49-
None,
50-
SymbolKind::STRUCT,
51-
table.get_range(),
52-
);
86+
pub fn build_table_symbol(
87+
builder: &mut DocumentSymbolBuilder,
88+
table: LuaTableExpr,
89+
parent_id: LuaSyntaxId,
90+
inline_to_parent: bool,
91+
) -> Option<LuaSyntaxId> {
92+
let table_id = if inline_to_parent {
93+
parent_id
94+
} else {
95+
let symbol = LuaSymbol::new(
96+
"table".to_string(),
97+
None,
98+
SymbolKind::STRUCT,
99+
table.get_range(),
100+
);
53101

54-
builder.add_node_symbol(table.syntax().clone(), symbol);
102+
builder.add_node_symbol(table.syntax().clone(), symbol, Some(parent_id))
103+
};
55104

56105
if table.is_object() {
57106
for field in table.get_fields() {
@@ -65,9 +114,9 @@ pub fn build_table_symbol(builder: &mut DocumentSymbolBuilder, table: LuaTableEx
65114

66115
let symbol = LuaSymbol::new(str_key, None, SymbolKind::FIELD, field.get_range());
67116

68-
builder.add_node_symbol(field.syntax().clone(), symbol);
117+
builder.add_node_symbol(field.syntax().clone(), symbol, Some(table_id));
69118
}
70119
}
71120

72-
Some(())
121+
Some(table_id)
73122
}

0 commit comments

Comments
 (0)