diff options
Diffstat (limited to 'crates/libsyntax2')
-rw-r--r-- | crates/libsyntax2/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/libsyntax2/src/algo/mod.rs | 48 | ||||
-rw-r--r-- | crates/libsyntax2/src/syntax_kinds/mod.rs | 2 | ||||
-rw-r--r-- | crates/libsyntax2/src/yellow/syntax.rs | 11 | ||||
-rw-r--r-- | crates/libsyntax2/tests/test/main.rs | 48 |
5 files changed, 62 insertions, 49 deletions
diff --git a/crates/libsyntax2/Cargo.toml b/crates/libsyntax2/Cargo.toml index 5a76ea82b..4c4040fe5 100644 --- a/crates/libsyntax2/Cargo.toml +++ b/crates/libsyntax2/Cargo.toml | |||
@@ -12,4 +12,4 @@ drop_bomb = "0.1.4" | |||
12 | parking_lot = "0.6.0" | 12 | parking_lot = "0.6.0" |
13 | 13 | ||
14 | [dev-dependencies] | 14 | [dev-dependencies] |
15 | difference = "2.0.0" | 15 | assert_eq_text = { path = "../assert_eq_text" } |
diff --git a/crates/libsyntax2/src/algo/mod.rs b/crates/libsyntax2/src/algo/mod.rs index 263b58d97..6efdff12f 100644 --- a/crates/libsyntax2/src/algo/mod.rs +++ b/crates/libsyntax2/src/algo/mod.rs | |||
@@ -74,7 +74,6 @@ impl<'f> Iterator for LeafAtOffset<'f> { | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | |||
78 | pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { | 77 | pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRef { |
79 | assert!(is_subrange(root.range(), range)); | 78 | assert!(is_subrange(root.range(), range)); |
80 | let (left, right) = match ( | 79 | let (left, right) = match ( |
@@ -88,31 +87,33 @@ pub fn find_covering_node(root: SyntaxNodeRef, range: TextRange) -> SyntaxNodeRe | |||
88 | common_ancestor(left, right) | 87 | common_ancestor(left, right) |
89 | } | 88 | } |
90 | 89 | ||
91 | fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> { | ||
92 | for p in ancestors(n1) { | ||
93 | if ancestors(n2).any(|a| a == p) { | ||
94 | return p; | ||
95 | } | ||
96 | } | ||
97 | panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) | ||
98 | } | ||
99 | |||
100 | pub fn ancestors<'a>(node: SyntaxNodeRef<'a>) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | 90 | pub fn ancestors<'a>(node: SyntaxNodeRef<'a>) -> impl Iterator<Item=SyntaxNodeRef<'a>> { |
101 | Ancestors(Some(node)) | 91 | generate(Some(node), |&node| node.parent()) |
102 | } | 92 | } |
103 | 93 | ||
104 | #[derive(Debug)] | 94 | #[derive(Debug)] |
105 | struct Ancestors<'a>(Option<SyntaxNodeRef<'a>>); | 95 | pub enum Direction { |
96 | Forward, | ||
97 | Backward, | ||
98 | } | ||
106 | 99 | ||
107 | impl<'a> Iterator for Ancestors<'a> { | 100 | pub fn siblings<'a>( |
108 | type Item = SyntaxNodeRef<'a>; | 101 | node: SyntaxNodeRef<'a>, |
102 | direction: Direction | ||
103 | ) -> impl Iterator<Item=SyntaxNodeRef<'a>> { | ||
104 | generate(Some(node), move |&node| match direction { | ||
105 | Direction::Forward => node.next_sibling(), | ||
106 | Direction::Backward => node.prev_sibling(), | ||
107 | }) | ||
108 | } | ||
109 | 109 | ||
110 | fn next(&mut self) -> Option<Self::Item> { | 110 | fn common_ancestor<'a>(n1: SyntaxNodeRef<'a>, n2: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> { |
111 | self.0.take().map(|n| { | 111 | for p in ancestors(n1) { |
112 | self.0 = n.parent(); | 112 | if ancestors(n2).any(|a| a == p) { |
113 | n | 113 | return p; |
114 | }) | 114 | } |
115 | } | 115 | } |
116 | panic!("Can't find common ancestor of {:?} and {:?}", n1, n2) | ||
116 | } | 117 | } |
117 | 118 | ||
118 | fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | 119 | fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { |
@@ -122,3 +123,12 @@ fn contains_offset_nonstrict(range: TextRange, offset: TextUnit) -> bool { | |||
122 | fn is_subrange(range: TextRange, subrange: TextRange) -> bool { | 123 | fn is_subrange(range: TextRange, subrange: TextRange) -> bool { |
123 | range.start() <= subrange.start() && subrange.end() <= range.end() | 124 | range.start() <= subrange.start() && subrange.end() <= range.end() |
124 | } | 125 | } |
126 | |||
127 | fn generate<T>(seed: Option<T>, step: impl Fn(&T) -> Option<T>) -> impl Iterator<Item=T> { | ||
128 | ::itertools::unfold(seed, move |slot| { | ||
129 | slot.take().map(|curr| { | ||
130 | *slot = step(&curr); | ||
131 | curr | ||
132 | }) | ||
133 | }) | ||
134 | } | ||
diff --git a/crates/libsyntax2/src/syntax_kinds/mod.rs b/crates/libsyntax2/src/syntax_kinds/mod.rs index ed4fa5d4d..332cd13ac 100644 --- a/crates/libsyntax2/src/syntax_kinds/mod.rs +++ b/crates/libsyntax2/src/syntax_kinds/mod.rs | |||
@@ -17,7 +17,7 @@ pub(crate) struct SyntaxInfo { | |||
17 | } | 17 | } |
18 | 18 | ||
19 | impl SyntaxKind { | 19 | impl SyntaxKind { |
20 | pub(crate) fn is_trivia(self) -> bool { | 20 | pub fn is_trivia(self) -> bool { |
21 | match self { | 21 | match self { |
22 | WHITESPACE | COMMENT | DOC_COMMENT => true, | 22 | WHITESPACE | COMMENT | DOC_COMMENT => true, |
23 | _ => false, | 23 | _ => false, |
diff --git a/crates/libsyntax2/src/yellow/syntax.rs b/crates/libsyntax2/src/yellow/syntax.rs index a22275ed9..00f76e51c 100644 --- a/crates/libsyntax2/src/yellow/syntax.rs +++ b/crates/libsyntax2/src/yellow/syntax.rs | |||
@@ -101,6 +101,17 @@ impl<R: TreeRoot> SyntaxNode<R> { | |||
101 | }) | 101 | }) |
102 | } | 102 | } |
103 | 103 | ||
104 | pub fn prev_sibling(&self) -> Option<SyntaxNode<R>> { | ||
105 | let red = self.red(); | ||
106 | let parent = self.parent()?; | ||
107 | let prev_sibling_idx = red.index_in_parent()?.checked_sub(1)?; | ||
108 | let sibling_red = parent.red().get_child(prev_sibling_idx)?; | ||
109 | Some(SyntaxNode { | ||
110 | root: self.root.clone(), | ||
111 | red: sibling_red, | ||
112 | }) | ||
113 | } | ||
114 | |||
104 | pub fn is_leaf(&self) -> bool { | 115 | pub fn is_leaf(&self) -> bool { |
105 | self.first_child().is_none() | 116 | self.first_child().is_none() |
106 | } | 117 | } |
diff --git a/crates/libsyntax2/tests/test/main.rs b/crates/libsyntax2/tests/test/main.rs index 18e5bc4d4..64d080dfd 100644 --- a/crates/libsyntax2/tests/test/main.rs +++ b/crates/libsyntax2/tests/test/main.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | extern crate libsyntax2; | 1 | extern crate libsyntax2; |
2 | extern crate difference; | 2 | #[macro_use] |
3 | extern crate assert_eq_text; | ||
3 | 4 | ||
4 | use std::{ | 5 | use std::{ |
5 | fs, | 6 | fs, |
@@ -7,8 +8,6 @@ use std::{ | |||
7 | fmt::Write, | 8 | fmt::Write, |
8 | }; | 9 | }; |
9 | 10 | ||
10 | use difference::Changeset; | ||
11 | |||
12 | #[test] | 11 | #[test] |
13 | fn lexer_tests() { | 12 | fn lexer_tests() { |
14 | dir_tests(&["lexer"], |text| { | 13 | dir_tests(&["lexer"], |text| { |
@@ -63,10 +62,26 @@ pub fn dir_tests<F>(paths: &[&str], f: F) | |||
63 | } | 62 | } |
64 | } | 63 | } |
65 | 64 | ||
65 | const REWRITE: bool = false; | ||
66 | |||
66 | fn assert_equal_text(expected: &str, actual: &str, path: &Path) { | 67 | fn assert_equal_text(expected: &str, actual: &str, path: &Path) { |
67 | if expected != actual { | 68 | if expected == actual { |
68 | print_difference(expected, actual, path) | 69 | return; |
70 | } | ||
71 | let dir = project_dir(); | ||
72 | let path = path.strip_prefix(&dir).unwrap_or_else(|_| path); | ||
73 | if expected.trim() == actual.trim() { | ||
74 | println!("whitespace difference, rewriting"); | ||
75 | println!("file: {}\n", path.display()); | ||
76 | fs::write(path, actual).unwrap(); | ||
77 | return; | ||
78 | } | ||
79 | if REWRITE { | ||
80 | println!("rewriting {}", path.display()); | ||
81 | fs::write(path, actual).unwrap(); | ||
82 | return; | ||
69 | } | 83 | } |
84 | assert_eq_text!(expected, actual, "file: {}", path.display()); | ||
70 | } | 85 | } |
71 | 86 | ||
72 | fn collect_tests(paths: &[&str]) -> Vec<PathBuf> { | 87 | fn collect_tests(paths: &[&str]) -> Vec<PathBuf> { |
@@ -92,29 +107,6 @@ fn test_from_dir(dir: &Path) -> Vec<PathBuf> { | |||
92 | acc | 107 | acc |
93 | } | 108 | } |
94 | 109 | ||
95 | const REWRITE: bool = false; | ||
96 | |||
97 | fn print_difference(expected: &str, actual: &str, path: &Path) { | ||
98 | let dir = project_dir(); | ||
99 | let path = path.strip_prefix(&dir).unwrap_or_else(|_| path); | ||
100 | if expected.trim() == actual.trim() { | ||
101 | println!("whitespace difference, rewriting"); | ||
102 | println!("file: {}\n", path.display()); | ||
103 | fs::write(path, actual).unwrap(); | ||
104 | return; | ||
105 | } | ||
106 | if REWRITE { | ||
107 | println!("rewriting {}", path.display()); | ||
108 | fs::write(path, actual).unwrap(); | ||
109 | return; | ||
110 | } | ||
111 | let changeset = Changeset::new(actual, expected, "\n"); | ||
112 | println!("Expected:\n{}\n\nActual:\n{}\n", expected, actual); | ||
113 | print!("{}", changeset); | ||
114 | println!("file: {}\n", path.display()); | ||
115 | panic!("Comparison failed") | ||
116 | } | ||
117 | |||
118 | fn project_dir() -> PathBuf { | 110 | fn project_dir() -> PathBuf { |
119 | let dir = env!("CARGO_MANIFEST_DIR"); | 111 | let dir = env!("CARGO_MANIFEST_DIR"); |
120 | PathBuf::from(dir) | 112 | PathBuf::from(dir) |