aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r--crates/ra_syntax/src/ast/generated.rs60
-rw-r--r--crates/ra_syntax/src/grammar.ron19
-rw-r--r--crates/ra_syntax/tests/test.rs157
3 files changed, 96 insertions, 140 deletions
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index bf056131e..c73533861 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -523,7 +523,15 @@ impl<R: TreeRoot<RaTypes>> CastExprNode<R> {
523} 523}
524 524
525 525
526impl<'a> CastExpr<'a> {} 526impl<'a> CastExpr<'a> {
527 pub fn expr(self) -> Option<Expr<'a>> {
528 super::child_opt(self)
529 }
530
531 pub fn type_ref(self) -> Option<TypeRef<'a>> {
532 super::child_opt(self)
533 }
534}
527 535
528// Char 536// Char
529#[derive(Debug, Clone, Copy,)] 537#[derive(Debug, Clone, Copy,)]
@@ -1553,6 +1561,10 @@ impl<'a> LetStmt<'a> {
1553 super::child_opt(self) 1561 super::child_opt(self)
1554 } 1562 }
1555 1563
1564 pub fn type_ref(self) -> Option<TypeRef<'a>> {
1565 super::child_opt(self)
1566 }
1567
1556 pub fn initializer(self) -> Option<Expr<'a>> { 1568 pub fn initializer(self) -> Option<Expr<'a>> {
1557 super::child_opt(self) 1569 super::child_opt(self)
1558 } 1570 }
@@ -2312,6 +2324,10 @@ impl<'a> Param<'a> {
2312 pub fn pat(self) -> Option<Pat<'a>> { 2324 pub fn pat(self) -> Option<Pat<'a>> {
2313 super::child_opt(self) 2325 super::child_opt(self)
2314 } 2326 }
2327
2328 pub fn type_ref(self) -> Option<TypeRef<'a>> {
2329 super::child_opt(self)
2330 }
2315} 2331}
2316 2332
2317// ParamList 2333// ParamList
@@ -2394,7 +2410,11 @@ impl<R: TreeRoot<RaTypes>> ParenExprNode<R> {
2394} 2410}
2395 2411
2396 2412
2397impl<'a> ParenExpr<'a> {} 2413impl<'a> ParenExpr<'a> {
2414 pub fn expr(self) -> Option<Expr<'a>> {
2415 super::child_opt(self)
2416 }
2417}
2398 2418
2399// ParenType 2419// ParenType
2400#[derive(Debug, Clone, Copy,)] 2420#[derive(Debug, Clone, Copy,)]
@@ -2681,7 +2701,11 @@ impl<R: TreeRoot<RaTypes>> PathTypeNode<R> {
2681} 2701}
2682 2702
2683 2703
2684impl<'a> PathType<'a> {} 2704impl<'a> PathType<'a> {
2705 pub fn path(self) -> Option<Path<'a>> {
2706 super::child_opt(self)
2707 }
2708}
2685 2709
2686// PlaceholderPat 2710// PlaceholderPat
2687#[derive(Debug, Clone, Copy,)] 2711#[derive(Debug, Clone, Copy,)]
@@ -2829,7 +2853,11 @@ impl<R: TreeRoot<RaTypes>> PrefixExprNode<R> {
2829} 2853}
2830 2854
2831 2855
2832impl<'a> PrefixExpr<'a> {} 2856impl<'a> PrefixExpr<'a> {
2857 pub fn expr(self) -> Option<Expr<'a>> {
2858 super::child_opt(self)
2859 }
2860}
2833 2861
2834// RangeExpr 2862// RangeExpr
2835#[derive(Debug, Clone, Copy,)] 2863#[derive(Debug, Clone, Copy,)]
@@ -2940,7 +2968,11 @@ impl<R: TreeRoot<RaTypes>> RefExprNode<R> {
2940} 2968}
2941 2969
2942 2970
2943impl<'a> RefExpr<'a> {} 2971impl<'a> RefExpr<'a> {
2972 pub fn expr(self) -> Option<Expr<'a>> {
2973 super::child_opt(self)
2974 }
2975}
2944 2976
2945// RefPat 2977// RefPat
2946#[derive(Debug, Clone, Copy,)] 2978#[derive(Debug, Clone, Copy,)]
@@ -3051,7 +3083,11 @@ impl<R: TreeRoot<RaTypes>> RetTypeNode<R> {
3051} 3083}
3052 3084
3053 3085
3054impl<'a> RetType<'a> {} 3086impl<'a> RetType<'a> {
3087 pub fn type_ref(self) -> Option<TypeRef<'a>> {
3088 super::child_opt(self)
3089 }
3090}
3055 3091
3056// ReturnExpr 3092// ReturnExpr
3057#[derive(Debug, Clone, Copy,)] 3093#[derive(Debug, Clone, Copy,)]
@@ -3088,7 +3124,11 @@ impl<R: TreeRoot<RaTypes>> ReturnExprNode<R> {
3088} 3124}
3089 3125
3090 3126
3091impl<'a> ReturnExpr<'a> {} 3127impl<'a> ReturnExpr<'a> {
3128 pub fn expr(self) -> Option<Expr<'a>> {
3129 super::child_opt(self)
3130 }
3131}
3092 3132
3093// SelfParam 3133// SelfParam
3094#[derive(Debug, Clone, Copy,)] 3134#[derive(Debug, Clone, Copy,)]
@@ -3578,7 +3618,11 @@ impl<R: TreeRoot<RaTypes>> TryExprNode<R> {
3578} 3618}
3579 3619
3580 3620
3581impl<'a> TryExpr<'a> {} 3621impl<'a> TryExpr<'a> {
3622 pub fn expr(self) -> Option<Expr<'a>> {
3623 super::child_opt(self)
3624 }
3625}
3582 3626
3583// TupleExpr 3627// TupleExpr
3584#[derive(Debug, Clone, Copy,)] 3628#[derive(Debug, Clone, Copy,)]
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index eed67637e..e3b9032a0 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -254,7 +254,7 @@ Grammar(
254 ], 254 ],
255 options: [ "ParamList", ["body", "Block"], "RetType" ], 255 options: [ "ParamList", ["body", "Block"], "RetType" ],
256 ), 256 ),
257 "RetType": (), 257 "RetType": (options: ["TypeRef"]),
258 "StructDef": ( 258 "StructDef": (
259 traits: [ 259 traits: [
260 "NameOwner", 260 "NameOwner",
@@ -304,7 +304,7 @@ Grammar(
304 "ParenType": (), 304 "ParenType": (),
305 "TupleType": (), 305 "TupleType": (),
306 "NeverType": (), 306 "NeverType": (),
307 "PathType": (), 307 "PathType": (options: ["Path"]),
308 "PointerType": (), 308 "PointerType": (),
309 "ArrayType": (), 309 "ArrayType": (),
310 "SliceType": (), 310 "SliceType": (),
@@ -346,7 +346,7 @@ Grammar(
346 346
347 "TupleExpr": (), 347 "TupleExpr": (),
348 "ArrayExpr": (), 348 "ArrayExpr": (),
349 "ParenExpr": (), 349 "ParenExpr": (options: ["Expr"]),
350 "PathExpr": (options: ["Path"]), 350 "PathExpr": (options: ["Path"]),
351 "LambdaExpr": ( 351 "LambdaExpr": (
352 options: [ 352 options: [
@@ -377,7 +377,7 @@ Grammar(
377 "BlockExpr": ( 377 "BlockExpr": (
378 options: [ "Block" ] 378 options: [ "Block" ]
379 ), 379 ),
380 "ReturnExpr": (), 380 "ReturnExpr": (options: ["Expr"]),
381 "MatchExpr": ( 381 "MatchExpr": (
382 options: [ "Expr", "MatchArmList" ], 382 options: [ "Expr", "MatchArmList" ],
383 ), 383 ),
@@ -405,10 +405,10 @@ Grammar(
405 ), 405 ),
406 "IndexExpr": (), 406 "IndexExpr": (),
407 "FieldExpr": (), 407 "FieldExpr": (),
408 "TryExpr": (), 408 "TryExpr": (options: ["Expr"]),
409 "CastExpr": (), 409 "CastExpr": (options: ["Expr", "TypeRef"]),
410 "RefExpr": (), 410 "RefExpr": (options: ["Expr"]),
411 "PrefixExpr": (), 411 "PrefixExpr": (options: ["Expr"]),
412 "RangeExpr": (), 412 "RangeExpr": (),
413 "BinExpr": (), 413 "BinExpr": (),
414 "String": (), 414 "String": (),
@@ -499,6 +499,7 @@ Grammar(
499 ), 499 ),
500 "LetStmt": ( options: [ 500 "LetStmt": ( options: [
501 ["pat", "Pat"], 501 ["pat", "Pat"],
502 ["type_ref", "TypeRef"],
502 ["initializer", "Expr"], 503 ["initializer", "Expr"],
503 ]), 504 ]),
504 "Condition": ( 505 "Condition": (
@@ -521,7 +522,7 @@ Grammar(
521 ), 522 ),
522 "SelfParam": (), 523 "SelfParam": (),
523 "Param": ( 524 "Param": (
524 options: [ "Pat" ], 525 options: [ "Pat", "TypeRef" ],
525 ), 526 ),
526 "UseItem": ( 527 "UseItem": (
527 options: [ "UseTree" ] 528 options: [ "UseTree" ]
diff --git a/crates/ra_syntax/tests/test.rs b/crates/ra_syntax/tests/test.rs
index 4266864bd..2235dc401 100644
--- a/crates/ra_syntax/tests/test.rs
+++ b/crates/ra_syntax/tests/test.rs
@@ -1,14 +1,13 @@
1extern crate ra_syntax; 1extern crate ra_syntax;
2#[macro_use]
3extern crate test_utils; 2extern crate test_utils;
4extern crate walkdir; 3extern crate walkdir;
5 4
6use std::{ 5use std::{
7 fmt::Write, 6 fmt::Write,
8 fs, 7 path::{PathBuf, Component},
9 path::{Path, PathBuf, Component},
10}; 8};
11 9
10use test_utils::{project_dir, dir_tests, read_text, collect_tests};
12use ra_syntax::{ 11use ra_syntax::{
13 utils::{check_fuzz_invariants, dump_tree}, 12 utils::{check_fuzz_invariants, dump_tree},
14 SourceFileNode, 13 SourceFileNode,
@@ -16,7 +15,7 @@ use ra_syntax::{
16 15
17#[test] 16#[test]
18fn lexer_tests() { 17fn lexer_tests() {
19 dir_tests(&["lexer"], |text, _| { 18 dir_tests(&test_data_dir(), &["lexer"], |text, _| {
20 let tokens = ra_syntax::tokenize(text); 19 let tokens = ra_syntax::tokenize(text);
21 dump_tokens(&tokens, text) 20 dump_tokens(&tokens, text)
22 }) 21 })
@@ -24,33 +23,41 @@ fn lexer_tests() {
24 23
25#[test] 24#[test]
26fn parser_tests() { 25fn parser_tests() {
27 dir_tests(&["parser/inline/ok", "parser/ok"], |text, path| { 26 dir_tests(
28 let file = SourceFileNode::parse(text); 27 &test_data_dir(),
29 let errors = file.errors(); 28 &["parser/inline/ok", "parser/ok"],
30 assert_eq!( 29 |text, path| {
31 &*errors, 30 let file = SourceFileNode::parse(text);
32 &[] as &[ra_syntax::SyntaxError], 31 let errors = file.errors();
33 "There should be no errors in the file {:?}", 32 assert_eq!(
34 path.display() 33 &*errors,
35 ); 34 &[] as &[ra_syntax::SyntaxError],
36 dump_tree(file.syntax()) 35 "There should be no errors in the file {:?}",
37 }); 36 path.display()
38 dir_tests(&["parser/err", "parser/inline/err"], |text, path| { 37 );
39 let file = SourceFileNode::parse(text); 38 dump_tree(file.syntax())
40 let errors = file.errors(); 39 },
41 assert_ne!( 40 );
42 &*errors, 41 dir_tests(
43 &[] as &[ra_syntax::SyntaxError], 42 &test_data_dir(),
44 "There should be errors in the file {:?}", 43 &["parser/err", "parser/inline/err"],
45 path.display() 44 |text, path| {
46 ); 45 let file = SourceFileNode::parse(text);
47 dump_tree(file.syntax()) 46 let errors = file.errors();
48 }); 47 assert_ne!(
48 &*errors,
49 &[] as &[ra_syntax::SyntaxError],
50 "There should be errors in the file {:?}",
51 path.display()
52 );
53 dump_tree(file.syntax())
54 },
55 );
49} 56}
50 57
51#[test] 58#[test]
52fn parser_fuzz_tests() { 59fn parser_fuzz_tests() {
53 for (_, text) in collect_tests(&["parser/fuzz-failures"]) { 60 for (_, text) in collect_tests(&test_data_dir(), &["parser/fuzz-failures"]) {
54 check_fuzz_invariants(&text) 61 check_fuzz_invariants(&text)
55 } 62 }
56} 63}
@@ -92,102 +99,6 @@ fn self_hosting_parsing() {
92 "self_hosting_parsing found too few files - is it running in the right directory?" 99 "self_hosting_parsing found too few files - is it running in the right directory?"
93 ) 100 )
94} 101}
95/// Read file and normalize newlines.
96///
97/// `rustc` seems to always normalize `\r\n` newlines to `\n`:
98///
99/// ```
100/// let s = "
101/// ";
102/// assert_eq!(s.as_bytes(), &[10]);
103/// ```
104///
105/// so this should always be correct.
106fn read_text(path: &Path) -> String {
107 fs::read_to_string(path)
108 .expect(&format!("File at {:?} should be valid", path))
109 .replace("\r\n", "\n")
110}
111
112fn dir_tests<F>(paths: &[&str], f: F)
113where
114 F: Fn(&str, &Path) -> String,
115{
116 for (path, input_code) in collect_tests(paths) {
117 let parse_tree = f(&input_code, &path);
118 let path = path.with_extension("txt");
119 if !path.exists() {
120 println!("\nfile: {}", path.display());
121 println!("No .txt file with expected result, creating...\n");
122 println!("{}\n{}", input_code, parse_tree);
123 fs::write(&path, &parse_tree).unwrap();
124 panic!("No expected result")
125 }
126 let expected = read_text(&path);
127 let expected = expected.as_str();
128 let parse_tree = parse_tree.as_str();
129 assert_equal_text(expected, parse_tree, &path);
130 }
131}
132
133const REWRITE: bool = false;
134
135fn assert_equal_text(expected: &str, actual: &str, path: &Path) {
136 if expected == actual {
137 return;
138 }
139 let dir = project_dir();
140 let pretty_path = path.strip_prefix(&dir).unwrap_or_else(|_| path);
141 if expected.trim() == actual.trim() {
142 println!("whitespace difference, rewriting");
143 println!("file: {}\n", pretty_path.display());
144 fs::write(path, actual).unwrap();
145 return;
146 }
147 if REWRITE {
148 println!("rewriting {}", pretty_path.display());
149 fs::write(path, actual).unwrap();
150 return;
151 }
152 assert_eq_text!(expected, actual, "file: {}", pretty_path.display());
153}
154
155fn collect_tests(paths: &[&str]) -> Vec<(PathBuf, String)> {
156 paths
157 .iter()
158 .flat_map(|path| {
159 let path = test_data_dir().join(path);
160 test_from_dir(&path).into_iter()
161 })
162 .map(|path| {
163 let text = read_text(&path);
164 (path, text)
165 })
166 .collect()
167}
168
169fn test_from_dir(dir: &Path) -> Vec<PathBuf> {
170 let mut acc = Vec::new();
171 for file in fs::read_dir(&dir).unwrap() {
172 let file = file.unwrap();
173 let path = file.path();
174 if path.extension().unwrap_or_default() == "rs" {
175 acc.push(path);
176 }
177 }
178 acc.sort();
179 acc
180}
181
182fn project_dir() -> PathBuf {
183 let dir = env!("CARGO_MANIFEST_DIR");
184 PathBuf::from(dir)
185 .parent()
186 .unwrap()
187 .parent()
188 .unwrap()
189 .to_owned()
190}
191 102
192fn test_data_dir() -> PathBuf { 103fn test_data_dir() -> PathBuf {
193 project_dir().join("crates/ra_syntax/tests/data") 104 project_dir().join("crates/ra_syntax/tests/data")