aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/Cargo.toml2
-rw-r--r--cli/src/main.rs35
-rw-r--r--libeditor/src/lib.rs47
3 files changed, 69 insertions, 15 deletions
diff --git a/cli/Cargo.toml b/cli/Cargo.toml
index a259eef63..ac89a48d3 100644
--- a/cli/Cargo.toml
+++ b/cli/Cargo.toml
@@ -7,5 +7,5 @@ publish = false
7[dependencies] 7[dependencies]
8clap = "2.32.0" 8clap = "2.32.0"
9failure = "0.1.1" 9failure = "0.1.1"
10libsyntax2 = { path = "../" } 10libeditor = { path = "../libeditor" }
11tools = { path = "../tools" } 11tools = { path = "../tools" }
diff --git a/cli/src/main.rs b/cli/src/main.rs
index 0044841ed..a3a317c69 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -1,13 +1,16 @@
1extern crate clap; 1extern crate clap;
2#[macro_use] 2#[macro_use]
3extern crate failure; 3extern crate failure;
4extern crate libsyntax2; 4extern crate libeditor;
5extern crate tools; 5extern crate tools;
6 6
7use std::{
8 fs, io::Read, path::Path,
9 time::Instant
10};
7use clap::{App, Arg, SubCommand}; 11use clap::{App, Arg, SubCommand};
8use std::time::Instant;
9use std::{fs, io::Read, path::Path};
10use tools::collect_tests; 12use tools::collect_tests;
13use libeditor::File;
11 14
12type Result<T> = ::std::result::Result<T, failure::Error>; 15type Result<T> = ::std::result::Result<T, failure::Error>;
13 16
@@ -30,11 +33,21 @@ fn main() -> Result<()> {
30 ), 33 ),
31 ) 34 )
32 .subcommand(SubCommand::with_name("parse")) 35 .subcommand(SubCommand::with_name("parse"))
36 .subcommand(SubCommand::with_name("symbols"))
33 .get_matches(); 37 .get_matches();
34 match matches.subcommand() { 38 match matches.subcommand() {
35 ("parse", _) => { 39 ("parse", _) => {
36 let tree = parse()?; 40 let start = Instant::now();
37 println!("{}", tree); 41 let file = file()?;
42 let elapsed = start.elapsed();
43 println!("{}", file.syntax_tree());
44 eprintln!("parsing: {:?}", elapsed);
45 }
46 ("symbols", _) => {
47 let file = file()?;
48 for s in file.symbols() {
49 println!("{:?}", s);
50 }
38 } 51 }
39 ("render-test", Some(matches)) => { 52 ("render-test", Some(matches)) => {
40 let file = matches.value_of("file").unwrap(); 53 let file = matches.value_of("file").unwrap();
@@ -49,13 +62,9 @@ fn main() -> Result<()> {
49 Ok(()) 62 Ok(())
50} 63}
51 64
52fn parse() -> Result<String> { 65fn file() -> Result<File> {
53 let text = read_stdin()?; 66 let text = read_stdin()?;
54 let start = Instant::now(); 67 Ok(File::new(&text))
55 let file = libsyntax2::parse(&text);
56 eprintln!("elapsed {:?}", start.elapsed());
57 let tree = libsyntax2::utils::dump_tree(&file);
58 Ok(tree)
59} 68}
60 69
61fn read_stdin() -> Result<String> { 70fn read_stdin() -> Result<String> {
@@ -74,7 +83,7 @@ fn render_test(file: &Path, line: usize) -> Result<(String, String)> {
74 None => bail!("No test found at line {} at {}", line, file.display()), 83 None => bail!("No test found at line {} at {}", line, file.display()),
75 Some((_start_line, test)) => test, 84 Some((_start_line, test)) => test,
76 }; 85 };
77 let file = libsyntax2::parse(&test.text); 86 let file = File::new(&test.text);
78 let tree = libsyntax2::utils::dump_tree(&file); 87 let tree = file.syntax_tree();
79 Ok((test.text, tree)) 88 Ok((test.text, tree))
80} 89}
diff --git a/libeditor/src/lib.rs b/libeditor/src/lib.rs
index 119bdb2d6..091aed125 100644
--- a/libeditor/src/lib.rs
+++ b/libeditor/src/lib.rs
@@ -2,6 +2,7 @@ extern crate libsyntax2;
2extern crate text_unit; 2extern crate text_unit;
3 3
4use libsyntax2::{ 4use libsyntax2::{
5 SyntaxNodeRef,
5 algo::walk, 6 algo::walk,
6 SyntaxKind::*, 7 SyntaxKind::*,
7}; 8};
@@ -16,6 +17,13 @@ pub struct HighlightedRange {
16 pub tag: &'static str, 17 pub tag: &'static str,
17} 18}
18 19
20#[derive(Debug)]
21pub struct Symbol {
22 // pub parent: ???,
23 pub name: String,
24 pub range: TextRange,
25}
26
19impl File { 27impl File {
20 pub fn new(text: &str) -> File { 28 pub fn new(text: &str) -> File {
21 File { 29 File {
@@ -41,7 +49,7 @@ impl File {
41 }; 49 };
42 res.push(HighlightedRange { 50 res.push(HighlightedRange {
43 range: node.range(), 51 range: node.range(),
44 tag 52 tag,
45 }) 53 })
46 } 54 }
47 res 55 res
@@ -50,4 +58,41 @@ impl File {
50 pub fn syntax_tree(&self) -> String { 58 pub fn syntax_tree(&self) -> String {
51 ::libsyntax2::utils::dump_tree(&self.inner.syntax()) 59 ::libsyntax2::utils::dump_tree(&self.inner.syntax())
52 } 60 }
61
62 pub fn symbols(&self) -> Vec<Symbol> {
63 let syntax = self.inner.syntax();
64 let res: Vec<Symbol> = walk::preorder(syntax.as_ref())
65 .filter_map(Declaration::cast)
66 .filter_map(|decl| {
67 let name = decl.name()?;
68 let range = decl.range();
69 Some(Symbol { name, range })
70 })
71 .collect();
72 res // NLL :-(
73 }
74}
75
76
77struct Declaration<'f>(SyntaxNodeRef<'f>);
78
79impl<'f> Declaration<'f> {
80 fn cast(node: SyntaxNodeRef<'f>) -> Option<Declaration<'f>> {
81 match node.kind() {
82 | STRUCT_ITEM | ENUM_ITEM | FN_ITEM | TRAIT_ITEM
83 | CONST_ITEM | STATIC_ITEM | MOD_ITEM | NAMED_FIELD
84 | TYPE_ITEM => Some(Declaration(node)),
85 _ => None
86 }
87 }
88
89 fn name(&self) -> Option<String> {
90 let name = self.0.children()
91 .find(|child| child.kind() == NAME)?;
92 Some(name.text())
93 }
94
95 fn range(&self) -> TextRange {
96 self.0.range()
97 }
53} 98}