aboutsummaryrefslogtreecommitdiff
path: root/crates/libeditor
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-14 09:20:09 +0100
committerAleksey Kladov <[email protected]>2018-08-14 09:20:09 +0100
commit2b828c68e8acda628d6e3a36827d1ffd9c9aaec6 (patch)
treee63ec3bb469eaaf996bbc45c038e66395c04ed23 /crates/libeditor
parent49ab44102496ac8c4a05b00c584adecf583f4d87 (diff)
separete structure from symbols
Diffstat (limited to 'crates/libeditor')
-rw-r--r--crates/libeditor/src/lib.rs2
-rw-r--r--crates/libeditor/src/symbols.rs82
-rw-r--r--crates/libeditor/tests/test.rs26
3 files changed, 88 insertions, 22 deletions
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};
19pub use self::{ 19pub use self::{
20 line_index::{LineIndex, LineCol}, 20 line_index::{LineIndex, LineCol},
21 extend_selection::extend_selection, 21 extend_selection::extend_selection,
22 symbols::{FileSymbol, file_symbols}, 22 symbols::{StructureNode, file_structure, FileSymbol, file_symbols},
23 edit::{EditBuilder, Edit, AtomEdit}, 23 edit::{EditBuilder, Edit, AtomEdit},
24 code_actions::{flip_comma}, 24 code_actions::{flip_comma},
25}; 25};
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::{
4 ast::{self, NameOwner}, 4 ast::{self, NameOwner},
5 algo::{ 5 algo::{
6 visit::{visitor, Visitor}, 6 visit::{visitor, Visitor},
7 walk::{walk, WalkEvent}, 7 walk::{walk, WalkEvent, preorder},
8 }, 8 },
9 SyntaxKind::*,
9}; 10};
10use TextRange; 11use TextRange;
11 12
12#[derive(Debug)] 13#[derive(Debug)]
13pub struct FileSymbol { 14pub struct StructureNode {
14 pub parent: Option<usize>, 15 pub parent: Option<usize>,
15 pub name: SmolStr, 16 pub label: String,
16 pub name_range: TextRange, 17 pub navigation_range: TextRange,
17 pub node_range: TextRange, 18 pub node_range: TextRange,
18 pub kind: SyntaxKind, 19 pub kind: SyntaxKind,
19} 20}
20 21
22#[derive(Debug)]
23pub struct FileSymbol {
24 pub name: SmolStr,
25 pub node_range: TextRange,
26 pub kind: SyntaxKind,
27}
21 28
22pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> { 29pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> {
30 let syntax = file.syntax();
31 preorder(syntax.as_ref())
32 .filter_map(to_symbol)
33 .collect()
34}
35
36fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
37 fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option<FileSymbol> {
38 let name = node.name()?;
39 Some(FileSymbol {
40 name: name.text(),
41 node_range: node.syntax().range(),
42 kind: node.syntax().kind(),
43 })
44 }
45 visitor()
46 .visit(decl::<ast::FnDef<_>>)
47 .visit(decl::<ast::StructDef<_>>)
48 .visit(decl::<ast::EnumDef<_>>)
49 .visit(decl::<ast::TraitDef<_>>)
50 .visit(decl::<ast::Module<_>>)
51 .visit(decl::<ast::TypeDef<_>>)
52 .visit(decl::<ast::ConstDef<_>>)
53 .visit(decl::<ast::StaticDef<_>>)
54 .accept(node)?
55}
56
57
58pub fn file_structure(file: &ast::File) -> Vec<StructureNode> {
23 let mut res = Vec::new(); 59 let mut res = Vec::new();
24 let mut stack = Vec::new(); 60 let mut stack = Vec::new();
25 let syntax = file.syntax(); 61 let syntax = file.syntax();
@@ -27,7 +63,7 @@ pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> {
27 for event in walk(syntax.as_ref()) { 63 for event in walk(syntax.as_ref()) {
28 match event { 64 match event {
29 WalkEvent::Enter(node) => { 65 WalkEvent::Enter(node) => {
30 match to_symbol(node) { 66 match structure_node(node) {
31 Some(mut symbol) => { 67 Some(mut symbol) => {
32 symbol.parent = stack.last().map(|&n| n); 68 symbol.parent = stack.last().map(|&n| n);
33 stack.push(res.len()); 69 stack.push(res.len());
@@ -37,7 +73,7 @@ pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> {
37 } 73 }
38 } 74 }
39 WalkEvent::Exit(node) => { 75 WalkEvent::Exit(node) => {
40 if to_symbol(node).is_some() { 76 if structure_node(node).is_some() {
41 stack.pop().unwrap(); 77 stack.pop().unwrap();
42 } 78 }
43 } 79 }
@@ -46,13 +82,13 @@ pub fn file_symbols(file: &ast::File) -> Vec<FileSymbol> {
46 res 82 res
47} 83}
48 84
49fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> { 85fn structure_node(node: SyntaxNodeRef) -> Option<StructureNode> {
50 fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option<FileSymbol> { 86 fn decl<'a, N: NameOwner<&'a SyntaxRoot>>(node: N) -> Option<StructureNode> {
51 let name = node.name()?; 87 let name = node.name()?;
52 Some(FileSymbol { 88 Some(StructureNode {
53 parent: None, 89 parent: None,
54 name: name.text(), 90 label: name.text().to_string(),
55 name_range: name.syntax().range(), 91 navigation_range: name.syntax().range(),
56 node_range: node.syntax().range(), 92 node_range: node.syntax().range(),
57 kind: node.syntax().kind(), 93 kind: node.syntax().kind(),
58 }) 94 })
@@ -67,5 +103,29 @@ fn to_symbol(node: SyntaxNodeRef) -> Option<FileSymbol> {
67 .visit(decl::<ast::TypeDef<_>>) 103 .visit(decl::<ast::TypeDef<_>>)
68 .visit(decl::<ast::ConstDef<_>>) 104 .visit(decl::<ast::ConstDef<_>>)
69 .visit(decl::<ast::StaticDef<_>>) 105 .visit(decl::<ast::StaticDef<_>>)
106 .visit(|im: ast::ImplItem<_>| {
107 let mut label = String::new();
108 let brace = im.syntax().children()
109 .find(|it| {
110 let stop = it.kind() == L_CURLY;
111 if !stop {
112 label.push_str(&it.text());
113 }
114 stop
115 })?;
116 let navigation_range = TextRange::from_to(
117 im.syntax().range().start(),
118 brace.range().start(),
119 );
120
121 let node = StructureNode {
122 parent: None,
123 label,
124 navigation_range,
125 node_range: im.syntax().range(),
126 kind: im.syntax().kind(),
127 };
128 Some(node)
129 })
70 .accept(node)? 130 .accept(node)?
71} 131}
diff --git a/crates/libeditor/tests/test.rs b/crates/libeditor/tests/test.rs
index fab2e4ad3..97fa30e1f 100644
--- a/crates/libeditor/tests/test.rs
+++ b/crates/libeditor/tests/test.rs
@@ -9,7 +9,7 @@ use itertools::Itertools;
9use libsyntax2::AstNode; 9use libsyntax2::AstNode;
10use libeditor::{ 10use libeditor::{
11 File, TextUnit, TextRange, 11 File, TextUnit, TextRange,
12 highlight, runnables, extend_selection, file_symbols, flip_comma, 12 highlight, runnables, extend_selection, file_structure, flip_comma,
13}; 13};
14 14
15#[test] 15#[test]
@@ -66,7 +66,7 @@ fn test_foo() {}
66} 66}
67 67
68#[test] 68#[test]
69fn symbols() { 69fn test_structure() {
70 let file = file(r#" 70 let file = file(r#"
71struct Foo { 71struct Foo {
72 x: i32 72 x: i32
@@ -80,16 +80,22 @@ enum E { X, Y(i32) }
80type T = (); 80type T = ();
81static S: i32 = 92; 81static S: i32 = 92;
82const C: i32 = 92; 82const C: i32 = 92;
83
84impl E {}
85
86impl fmt::Debug for E {}
83"#); 87"#);
84 let symbols = file_symbols(&file); 88 let symbols = file_structure(&file);
85 dbg_eq( 89 dbg_eq(
86 r#"[FileSymbol { parent: None, name: "Foo", name_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF }, 90 r#"[StructureNode { parent: None, label: "Foo", navigation_range: [8; 11), node_range: [1; 26), kind: STRUCT_DEF },
87 FileSymbol { parent: None, name: "m", name_range: [32; 33), node_range: [28; 53), kind: MODULE }, 91 StructureNode { parent: None, label: "m", navigation_range: [32; 33), node_range: [28; 53), kind: MODULE },
88 FileSymbol { parent: Some(1), name: "bar", name_range: [43; 46), node_range: [40; 51), kind: FN_DEF }, 92 StructureNode { parent: Some(1), label: "bar", navigation_range: [43; 46), node_range: [40; 51), kind: FN_DEF },
89 FileSymbol { parent: None, name: "E", name_range: [60; 61), node_range: [55; 75), kind: ENUM_DEF }, 93 StructureNode { parent: None, label: "E", navigation_range: [60; 61), node_range: [55; 75), kind: ENUM_DEF },
90 FileSymbol { parent: None, name: "T", name_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF }, 94 StructureNode { parent: None, label: "T", navigation_range: [81; 82), node_range: [76; 88), kind: TYPE_DEF },
91 FileSymbol { parent: None, name: "S", name_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF }, 95 StructureNode { parent: None, label: "S", navigation_range: [96; 97), node_range: [89; 108), kind: STATIC_DEF },
92 FileSymbol { parent: None, name: "C", name_range: [115; 116), node_range: [109; 127), kind: CONST_DEF }]"#, 96 StructureNode { parent: None, label: "C", navigation_range: [115; 116), node_range: [109; 127), kind: CONST_DEF },
97 StructureNode { parent: None, label: "impl E ", navigation_range: [129; 136), node_range: [129; 138), kind: IMPL_ITEM },
98 StructureNode { parent: None, label: "impl fmt::Debug for E ", navigation_range: [140; 162), node_range: [140; 164), kind: IMPL_ITEM }]"#,
93 &symbols, 99 &symbols,
94 ) 100 )
95} 101}