aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor/src
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-11 10:28:59 +0100
committerAleksey Kladov <[email protected]>2018-08-11 10:28:59 +0100
commit7afd84febc76a75a3ed1be75c57ff35d7b8b3de6 (patch)
tree76eb2de7efc569c39cc721b7be298490b9647e0b /crates/libeditor/src
parentd5119133fc03694c6644cac9e307d1d496fc9bf2 (diff)
visitor
Diffstat (limited to 'crates/libeditor/src')
-rw-r--r--crates/libeditor/src/extend_selection.rs7
-rw-r--r--crates/libeditor/src/lib.rs14
-rw-r--r--crates/libeditor/src/symbols.rs67
3 files changed, 80 insertions, 8 deletions
diff --git a/crates/libeditor/src/extend_selection.rs b/crates/libeditor/src/extend_selection.rs
index 16d4bc084..ed7d9b3f7 100644
--- a/crates/libeditor/src/extend_selection.rs
+++ b/crates/libeditor/src/extend_selection.rs
@@ -1,11 +1,16 @@
1use libsyntax2::{ 1use libsyntax2::{
2 ast, AstNode,
2 TextRange, SyntaxNodeRef, 3 TextRange, SyntaxNodeRef,
3 SyntaxKind::WHITESPACE, 4 SyntaxKind::WHITESPACE,
4 algo::{find_leaf_at_offset, find_covering_node, ancestors}, 5 algo::{find_leaf_at_offset, find_covering_node, ancestors},
5}; 6};
6 7
8pub fn extend_selection(file: &ast::File, range: TextRange) -> Option<TextRange> {
9 let syntax = file.syntax();
10 extend(syntax.as_ref(), range)
11}
7 12
8pub(crate) fn extend_selection(root: SyntaxNodeRef, range: TextRange) -> Option<TextRange> { 13pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option<TextRange> {
9 if range.is_empty() { 14 if range.is_empty() {
10 let offset = range.start(); 15 let offset = range.start();
11 let mut leaves = find_leaf_at_offset(root, offset); 16 let mut leaves = find_leaf_at_offset(root, offset);
diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs
index 293fafae7..4ea344b17 100644
--- a/crates/libeditor/src/lib.rs
+++ b/crates/libeditor/src/lib.rs
@@ -2,16 +2,21 @@ extern crate libsyntax2;
2extern crate superslice; 2extern crate superslice;
3 3
4mod extend_selection; 4mod extend_selection;
5mod symbols;
5mod line_index; 6mod line_index;
6 7
7use libsyntax2::{ 8use libsyntax2::{
8 ast, 9 ast::{self, NameOwner},
9 SyntaxNodeRef, AstNode, 10 SyntaxNodeRef, AstNode,
10 algo::walk, 11 algo::walk,
11 SyntaxKind::*, 12 SyntaxKind::*,
12}; 13};
13pub use libsyntax2::{File, TextRange, TextUnit}; 14pub use libsyntax2::{File, TextRange, TextUnit};
14pub use self::line_index::{LineIndex, LineCol}; 15pub use self::{
16 line_index::{LineIndex, LineCol},
17 extend_selection::extend_selection,
18 symbols::{FileSymbol, file_symbols}
19};
15 20
16#[derive(Debug)] 21#[derive(Debug)]
17pub struct HighlightedRange { 22pub struct HighlightedRange {
@@ -108,11 +113,6 @@ pub fn symbols(file: &ast::File) -> Vec<Symbol> {
108 res // NLL :-( 113 res // NLL :-(
109} 114}
110 115
111pub fn extend_selection(file: &ast::File, range: TextRange) -> Option<TextRange> {
112 let syntax = file.syntax();
113 extend_selection::extend_selection(syntax.as_ref(), range)
114}
115
116pub fn runnables(file: &ast::File) -> Vec<Runnable> { 116pub fn runnables(file: &ast::File) -> Vec<Runnable> {
117 file 117 file
118 .functions() 118 .functions()
diff --git a/crates/libeditor/src/symbols.rs b/crates/libeditor/src/symbols.rs
new file mode 100644
index 000000000..3faf96868
--- /dev/null
+++ b/crates/libeditor/src/symbols.rs
@@ -0,0 +1,67 @@
1use libsyntax2::{
2 SyntaxKind, SyntaxNodeRef, SyntaxRoot, AstNode,
3 ast::{self, NameOwner},
4 algo::{
5 visit::{visitor, Visitor},
6 walk::{walk, WalkEvent},
7 },
8};
9use TextRange;
10
11#[derive(Debug)]
12pub struct FileSymbol {
13 pub parent: Option<usize>,
14 pub name: String,
15 pub name_range: TextRange,
16 pub node_range: TextRange,
17 pub kind: SyntaxKind,
18}
19
20
21pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> {
22 let mut res = Vec::new();
23 let mut stack = Vec::new();
24 let syntax = file.syntax();
25
26 for event in walk(syntax.as_ref()) {
27 match event {
28 WalkEvent::Enter(node) => {
29 match to_symbol(node) {
30 Some(mut symbol) => {
31 symbol.parent = stack.last().map(|&n| n);
32 stack.push(res.len());
33 res.push(symbol);
34 }
35 None => (),
36 }
37 }
38 WalkEvent::Exit(node) => {
39 if to_symbol(node).is_some() {
40 stack.pop().unwrap();
41 }
42 }
43 }
44 }
45 res
46}
47
48fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
49 fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option<FileSymbol> {
50 let name = node.name()?;
51 Some(FileSymbol {
52 parent: None,
53 name: name.text(),
54 name_range: name.syntax().range(),
55 node_range: node.syntax().range(),
56 kind: node.syntax().kind(),
57 })
58 }
59
60 visitor()
61 .visit(decl::<ast::Function<_>>)
62 .visit(decl::<ast::Struct<_>>)
63 .visit(decl::<ast::Enum<_>>)
64 .visit(decl::<ast::Trait<_>>)
65 .visit(decl::<ast::Module<_>>)
66 .accept(node)?
67}