From 2b828c68e8acda628d6e3a36827d1ffd9c9aaec6 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Tue, 14 Aug 2018 11:20:09 +0300 Subject: separete structure from symbols --- crates/libeditor/src/lib.rs | 2 +- crates/libeditor/src/symbols.rs | 82 +++++++++++++++++++++++++++++++++++------ 2 files changed, 72 insertions(+), 12 deletions(-) (limited to 'crates/libeditor/src') diff --git a/crates/libeditor/src/lib.rs b/crates/libeditor/src/lib.rs index e5933cbd6..b40db2c66 100644 --- a/crates/libeditor/src/lib.rs +++ b/crates/libeditor/src/lib.rs @@ -19,7 +19,7 @@ pub use libsyntax2::{File, TextRange, TextUnit}; pub use self::{ line_index::{LineIndex, LineCol}, extend_selection::extend_selection, - symbols::{FileSymbol, file_symbols}, + symbols::{StructureNode, file_structure, FileSymbol, file_symbols}, edit::{EditBuilder, Edit, AtomEdit}, code_actions::{flip_comma}, }; diff --git a/crates/libeditor/src/symbols.rs b/crates/libeditor/src/symbols.rs index f1d5222f4..43f4164da 100644 --- a/crates/libeditor/src/symbols.rs +++ b/crates/libeditor/src/symbols.rs @@ -4,22 +4,58 @@ use libsyntax2::{ ast::{self, NameOwner}, algo::{ visit::{visitor, Visitor}, - walk::{walk, WalkEvent}, + walk::{walk, WalkEvent, preorder}, }, + SyntaxKind::*, }; use TextRange; #[derive(Debug)] -pub struct FileSymbol { +pub struct StructureNode { pub parent: Option, - pub name: SmolStr, - pub name_range: TextRange, + pub label: String, + pub navigation_range: TextRange, pub node_range: TextRange, pub kind: SyntaxKind, } +#[derive(Debug)] +pub struct FileSymbol { + pub name: SmolStr, + pub node_range: TextRange, + pub kind: SyntaxKind, +} pub fn file_symbols(file: &ast::File) -> Vec { + let syntax = file.syntax(); + preorder(syntax.as_ref()) + .filter_map(to_symbol) + .collect() +} + +fn to_symbol(node: SyntaxNodeRef) -> Option { + fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option { + let name = node.name()?; + Some(FileSymbol { + name: name.text(), + node_range: node.syntax().range(), + kind: node.syntax().kind(), + }) + } + visitor() + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .visit(decl::>) + .accept(node)? +} + + +pub fn file_structure(file: &ast::File) -> Vec { let mut res = Vec::new(); let mut stack = Vec::new(); let syntax = file.syntax(); @@ -27,7 +63,7 @@ pub fn file_symbols(file: &ast::File) -> Vec { for event in walk(syntax.as_ref()) { match event { WalkEvent::Enter(node) => { - match to_symbol(node) { + match structure_node(node) { Some(mut symbol) => { symbol.parent = stack.last().map(|&n| n); stack.push(res.len()); @@ -37,7 +73,7 @@ pub fn file_symbols(file: &ast::File) -> Vec { } } WalkEvent::Exit(node) => { - if to_symbol(node).is_some() { + if structure_node(node).is_some() { stack.pop().unwrap(); } } @@ -46,13 +82,13 @@ pub fn file_symbols(file: &ast::File) -> Vec { res } -fn to_symbol(node: SyntaxNodeRef) -> Option { - fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option { +fn structure_node(node: SyntaxNodeRef) -> Option { + fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option { let name = node.name()?; - Some(FileSymbol { + Some(StructureNode { parent: None, - name: name.text(), - name_range: name.syntax().range(), + label: name.text().to_string(), + navigation_range: name.syntax().range(), node_range: node.syntax().range(), kind: node.syntax().kind(), }) @@ -67,5 +103,29 @@ fn to_symbol(node: SyntaxNodeRef) -> Option { .visit(decl::>) .visit(decl::>) .visit(decl::>) + .visit(|im: ast::ImplItem<_>| { + let mut label = String::new(); + let brace = im.syntax().children() + .find(|it| { + let stop = it.kind() == L_CURLY; + if !stop { + label.push_str(&it.text()); + } + stop + })?; + let navigation_range = TextRange::from_to( + im.syntax().range().start(), + brace.range().start(), + ); + + let node = StructureNode { + parent: None, + label, + navigation_range, + node_range: im.syntax().range(), + kind: im.syntax().kind(), + }; + Some(node) + }) .accept(node)? } -- cgit v1.2.3