From 7afd84febc76a75a3ed1be75c57ff35d7b8b3de6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 11 Aug 2018 12:28:59 +0300 Subject: visitor --- crates/libeditor/src/symbols.rs | 67 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 crates/libeditor/src/symbols.rs (limited to 'crates/libeditor/src/symbols.rs') 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 @@ +use libsyntax2::{ + SyntaxKind, SyntaxNodeRef, SyntaxRoot, AstNode, + ast::{self, NameOwner}, + algo::{ + visit::{visitor, Visitor}, + walk::{walk, WalkEvent}, + }, +}; +use TextRange; + +#[derive(Debug)] +pub struct FileSymbol { + pub parent: Option, + pub name: String, + pub name_range: TextRange, + pub node_range: TextRange, + pub kind: SyntaxKind, +} + + +pub fn file_symbols(file: &ast::File) -> Vec { + let mut res = Vec::new(); + let mut stack = Vec::new(); + let syntax = file.syntax(); + + for event in walk(syntax.as_ref()) { + match event { + WalkEvent::Enter(node) => { + match to_symbol(node) { + Some(mut symbol) => { + symbol.parent = stack.last().map(|&n| n); + stack.push(res.len()); + res.push(symbol); + } + None => (), + } + } + WalkEvent::Exit(node) => { + if to_symbol(node).is_some() { + stack.pop().unwrap(); + } + } + } + } + res +} + +fn to_symbol(node: SyntaxNodeRef) -> Option { + fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option { + let name = node.name()?; + Some(FileSymbol { + parent: None, + name: name.text(), + name_range: name.syntax().range(), + node_range: node.syntax().range(), + kind: node.syntax().kind(), + }) + } + + visitor() + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .accept(node)? +} -- cgit v1.2.3