diff options
-rw-r--r-- | cli/Cargo.toml | 2 | ||||
-rw-r--r-- | cli/src/main.rs | 35 | ||||
-rw-r--r-- | libeditor/src/lib.rs | 47 |
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] |
8 | clap = "2.32.0" | 8 | clap = "2.32.0" |
9 | failure = "0.1.1" | 9 | failure = "0.1.1" |
10 | libsyntax2 = { path = "../" } | 10 | libeditor = { path = "../libeditor" } |
11 | tools = { path = "../tools" } | 11 | tools = { 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 @@ | |||
1 | extern crate clap; | 1 | extern crate clap; |
2 | #[macro_use] | 2 | #[macro_use] |
3 | extern crate failure; | 3 | extern crate failure; |
4 | extern crate libsyntax2; | 4 | extern crate libeditor; |
5 | extern crate tools; | 5 | extern crate tools; |
6 | 6 | ||
7 | use std::{ | ||
8 | fs, io::Read, path::Path, | ||
9 | time::Instant | ||
10 | }; | ||
7 | use clap::{App, Arg, SubCommand}; | 11 | use clap::{App, Arg, SubCommand}; |
8 | use std::time::Instant; | ||
9 | use std::{fs, io::Read, path::Path}; | ||
10 | use tools::collect_tests; | 12 | use tools::collect_tests; |
13 | use libeditor::File; | ||
11 | 14 | ||
12 | type Result<T> = ::std::result::Result<T, failure::Error>; | 15 | type 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 | ||
52 | fn parse() -> Result<String> { | 65 | fn 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 | ||
61 | fn read_stdin() -> Result<String> { | 70 | fn 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; | |||
2 | extern crate text_unit; | 2 | extern crate text_unit; |
3 | 3 | ||
4 | use libsyntax2::{ | 4 | use 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)] | ||
21 | pub struct Symbol { | ||
22 | // pub parent: ???, | ||
23 | pub name: String, | ||
24 | pub range: TextRange, | ||
25 | } | ||
26 | |||
19 | impl File { | 27 | impl 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 | |||
77 | struct Declaration<'f>(SyntaxNodeRef<'f>); | ||
78 | |||
79 | impl<'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 | } |