Skip to content

Commit 3205940

Browse files
committed
Don't emit assigned objects in nested contexts as document symbols
1 parent 0704a05 commit 3205940

File tree

3 files changed

+206
-59
lines changed

3 files changed

+206
-59
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
source: crates/ark/src/lsp/symbols.rs
3+
expression: "test_symbol(\"foo <- function() { bar <- function() 1 }\")"
4+
---
5+
[
6+
DocumentSymbol {
7+
name: "foo",
8+
detail: Some(
9+
"function()",
10+
),
11+
kind: Function,
12+
tags: None,
13+
deprecated: None,
14+
range: Range {
15+
start: Position {
16+
line: 0,
17+
character: 0,
18+
},
19+
end: Position {
20+
line: 0,
21+
character: 41,
22+
},
23+
},
24+
selection_range: Range {
25+
start: Position {
26+
line: 0,
27+
character: 0,
28+
},
29+
end: Position {
30+
line: 0,
31+
character: 41,
32+
},
33+
},
34+
children: Some(
35+
[
36+
DocumentSymbol {
37+
name: "bar",
38+
detail: Some(
39+
"function()",
40+
),
41+
kind: Function,
42+
tags: None,
43+
deprecated: None,
44+
range: Range {
45+
start: Position {
46+
line: 0,
47+
character: 20,
48+
},
49+
end: Position {
50+
line: 0,
51+
character: 39,
52+
},
53+
},
54+
selection_range: Range {
55+
start: Position {
56+
line: 0,
57+
character: 20,
58+
},
59+
end: Position {
60+
line: 0,
61+
character: 39,
62+
},
63+
},
64+
children: Some(
65+
[],
66+
),
67+
},
68+
],
69+
),
70+
},
71+
]
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
---
2+
source: crates/ark/src/lsp/symbols.rs
3+
expression: "test_symbol(\"\nlocal({\n inner1 <- 1 # Not a symbol\n})\na <- function() {\n inner2 <- 2 # Not a symbol\n inner3 <- function() 3 # Symbol\n}\n\")"
4+
---
5+
[
6+
DocumentSymbol {
7+
name: "a",
8+
detail: Some(
9+
"function()",
10+
),
11+
kind: Function,
12+
tags: None,
13+
deprecated: None,
14+
range: Range {
15+
start: Position {
16+
line: 4,
17+
character: 0,
18+
},
19+
end: Position {
20+
line: 7,
21+
character: 1,
22+
},
23+
},
24+
selection_range: Range {
25+
start: Position {
26+
line: 4,
27+
character: 0,
28+
},
29+
end: Position {
30+
line: 7,
31+
character: 1,
32+
},
33+
},
34+
children: Some(
35+
[
36+
DocumentSymbol {
37+
name: "inner3",
38+
detail: Some(
39+
"function()",
40+
),
41+
kind: Function,
42+
tags: None,
43+
deprecated: None,
44+
range: Range {
45+
start: Position {
46+
line: 6,
47+
character: 2,
48+
},
49+
end: Position {
50+
line: 6,
51+
character: 24,
52+
},
53+
},
54+
selection_range: Range {
55+
start: Position {
56+
line: 6,
57+
character: 2,
58+
},
59+
end: Position {
60+
line: 6,
61+
character: 24,
62+
},
63+
},
64+
children: Some(
65+
[],
66+
),
67+
},
68+
],
69+
),
70+
},
71+
]

crates/ark/src/lsp/symbols.rs

Lines changed: 64 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,15 @@ struct Section {
122122
children: Vec<DocumentSymbol>,
123123
}
124124

125-
struct CollectContext;
125+
struct CollectContext {
126+
top_level: bool,
127+
}
128+
129+
impl CollectContext {
130+
fn new() -> Self {
131+
Self { top_level: true }
132+
}
133+
}
126134

127135
pub(crate) fn document_symbols(
128136
state: &WorldState,
@@ -138,8 +146,13 @@ pub(crate) fn document_symbols(
138146
let mut result = Vec::new();
139147

140148
// Extract and process all symbols from the AST
141-
let mut ctx = CollectContext;
142-
if let Err(err) = collect_symbols(&mut ctx, &root_node, contents, 0, &mut result) {
149+
if let Err(err) = collect_symbols(
150+
&mut CollectContext::new(),
151+
&root_node,
152+
contents,
153+
0,
154+
&mut result,
155+
) {
143156
log::error!("Failed to collect symbols: {err:?}");
144157
return Ok(Vec::new());
145158
}
@@ -156,7 +169,12 @@ fn collect_symbols(
156169
symbols: &mut Vec<DocumentSymbol>,
157170
) -> anyhow::Result<()> {
158171
match node.node_type() {
159-
NodeType::Program | NodeType::BracedExpression => {
172+
NodeType::Program => {
173+
collect_sections(ctx, node, contents, current_level, symbols)?;
174+
},
175+
176+
NodeType::BracedExpression => {
177+
ctx.top_level = false;
160178
collect_sections(ctx, node, contents, current_level, symbols)?;
161179
},
162180

@@ -428,18 +446,25 @@ fn collect_assignment(
428446
return collect_assignment_with_function(ctx, node, contents, symbols);
429447
}
430448

431-
// Otherwise, collect as generic object
432-
let name = contents.node_slice(&lhs)?.to_string();
449+
if ctx.top_level {
450+
// Collect as generic object, but only if we're at top-level. Assigned
451+
// objects in nested functions and blocks cause the outline to become
452+
// too busy.
453+
let name = contents.node_slice(&lhs)?.to_string();
433454

434-
let start = convert_point_to_position(contents, lhs.start_position());
435-
let end = convert_point_to_position(contents, lhs.end_position());
455+
let start = convert_point_to_position(contents, lhs.start_position());
456+
let end = convert_point_to_position(contents, lhs.end_position());
436457

437-
// Now recurse into RHS
438-
let mut children = Vec::new();
439-
collect_symbols(ctx, &rhs, contents, 0, &mut children)?;
458+
// Now recurse into RHS
459+
let mut children = Vec::new();
460+
collect_symbols(ctx, &rhs, contents, 0, &mut children)?;
440461

441-
let symbol = new_symbol_node(name, SymbolKind::VARIABLE, Range { start, end }, children);
442-
symbols.push(symbol);
462+
let symbol = new_symbol_node(name, SymbolKind::VARIABLE, Range { start, end }, children);
463+
symbols.push(symbol);
464+
} else {
465+
// Recurse into RHS
466+
collect_symbols(ctx, &rhs, contents, 0, symbols)?;
467+
}
443468

444469
Ok(())
445470
}
@@ -544,8 +569,14 @@ mod tests {
544569
let node = doc.ast.root_node();
545570

546571
let mut symbols = Vec::new();
547-
let mut ctx = CollectContext;
548-
collect_symbols(&mut ctx, &node, &doc.contents, 0, &mut symbols).unwrap();
572+
collect_symbols(
573+
&mut CollectContext::new(),
574+
&node,
575+
&doc.contents,
576+
0,
577+
&mut symbols,
578+
)
579+
.unwrap();
549580
symbols
550581
}
551582

@@ -623,33 +654,7 @@ mod tests {
623654

624655
#[test]
625656
fn test_symbol_assignment_function_nested() {
626-
let range = Range {
627-
start: Position {
628-
line: 0,
629-
character: 20,
630-
},
631-
end: Position {
632-
line: 0,
633-
character: 23,
634-
},
635-
};
636-
let bar = new_symbol(String::from("bar"), SymbolKind::VARIABLE, range);
637-
638-
let range = Range {
639-
start: Position {
640-
line: 0,
641-
character: 0,
642-
},
643-
end: Position {
644-
line: 0,
645-
character: 30,
646-
},
647-
};
648-
let mut foo = new_symbol(String::from("foo"), SymbolKind::FUNCTION, range);
649-
foo.children = Some(vec![bar]);
650-
foo.detail = Some(String::from("function()"));
651-
652-
assert_eq!(test_symbol("foo <- function() { bar <- 1 }"), vec![foo]);
657+
insta::assert_debug_snapshot!(test_symbol("foo <- function() { bar <- function() 1 }"));
653658
}
654659

655660
#[test]
@@ -667,23 +672,6 @@ foo <- function() {
667672
));
668673
}
669674

670-
#[test]
671-
fn test_symbol_braced_list() {
672-
let range = Range {
673-
start: Position {
674-
line: 0,
675-
character: 2,
676-
},
677-
end: Position {
678-
line: 0,
679-
character: 5,
680-
},
681-
};
682-
let foo = new_symbol(String::from("foo"), SymbolKind::VARIABLE, range);
683-
684-
assert_eq!(test_symbol("{ foo <- 1 }"), vec![foo]);
685-
}
686-
687675
#[test]
688676
fn test_symbol_section_ranges_extend() {
689677
let symbols = test_symbol(
@@ -843,4 +831,21 @@ class <- r6::r6class(
843831
"
844832
));
845833
}
834+
835+
#[test]
836+
// Assigned variables in nested contexts are not emitted as symbols
837+
fn test_symbol_nested_assignments() {
838+
insta::assert_debug_snapshot!(test_symbol(
839+
"
840+
local({
841+
inner1 <- 1 # Not a symbol
842+
})
843+
a <- function() {
844+
inner2 <- 2 # Not a symbol
845+
inner3 <- function() 3 # Symbol
846+
}
847+
"
848+
));
849+
assert_eq!(test_symbol("{ foo <- 1 }"), vec![]);
850+
}
846851
}

0 commit comments

Comments
 (0)