diff options
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r-- | crates/ra_syntax/src/tests.rs | 80 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 6 |
2 files changed, 64 insertions, 22 deletions
diff --git a/crates/ra_syntax/src/tests.rs b/crates/ra_syntax/src/tests.rs index f79dc4f93..fb22b9e54 100644 --- a/crates/ra_syntax/src/tests.rs +++ b/crates/ra_syntax/src/tests.rs | |||
@@ -1,19 +1,28 @@ | |||
1 | use std::{ | 1 | use std::{ |
2 | fmt::Write, | 2 | fmt::Write, |
3 | path::{Component, PathBuf}, | 3 | path::{Component, Path, PathBuf}, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use test_utils::{collect_tests, dir_tests, project_dir, read_text}; | 6 | use test_utils::{collect_tests, dir_tests, project_dir, read_text}; |
7 | 7 | ||
8 | use crate::{fuzz, SourceFile}; | 8 | use crate::{fuzz, tokenize, Location, SourceFile, SyntaxError, TextRange, Token}; |
9 | 9 | ||
10 | #[test] | 10 | #[test] |
11 | fn lexer_tests() { | 11 | fn lexer_tests() { |
12 | dir_tests(&test_data_dir(), &["lexer"], |text, _| { | 12 | // FIXME: |
13 | // FIXME: add tests for errors (their format is up to discussion) | 13 | // * Add tests for unicode escapes in byte-character and [raw]-byte-string literals |
14 | let (tokens, _errors) = crate::tokenize(text); | 14 | // * Add tests for unescape errors |
15 | dump_tokens(&tokens, text) | 15 | |
16 | }) | 16 | dir_tests(&test_data_dir(), &["lexer/ok"], |text, path| { |
17 | let (tokens, errors) = tokenize(text); | ||
18 | assert_errors_are_absent(&errors, path); | ||
19 | dump_tokens_and_errors(&tokens, &errors, text) | ||
20 | }); | ||
21 | dir_tests(&test_data_dir(), &["lexer/err"], |text, path| { | ||
22 | let (tokens, errors) = tokenize(text); | ||
23 | assert_errors_are_present(&errors, path); | ||
24 | dump_tokens_and_errors(&tokens, &errors, text) | ||
25 | }); | ||
17 | } | 26 | } |
18 | 27 | ||
19 | #[test] | 28 | #[test] |
@@ -33,18 +42,13 @@ fn parser_tests() { | |||
33 | dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], |text, path| { | 42 | dir_tests(&test_data_dir(), &["parser/inline/ok", "parser/ok"], |text, path| { |
34 | let parse = SourceFile::parse(text); | 43 | let parse = SourceFile::parse(text); |
35 | let errors = parse.errors(); | 44 | let errors = parse.errors(); |
36 | assert_eq!( | 45 | assert_errors_are_absent(&errors, path); |
37 | errors, | ||
38 | &[] as &[crate::SyntaxError], | ||
39 | "There should be no errors in the file {:?}", | ||
40 | path.display(), | ||
41 | ); | ||
42 | parse.debug_dump() | 46 | parse.debug_dump() |
43 | }); | 47 | }); |
44 | dir_tests(&test_data_dir(), &["parser/err", "parser/inline/err"], |text, path| { | 48 | dir_tests(&test_data_dir(), &["parser/err", "parser/inline/err"], |text, path| { |
45 | let parse = SourceFile::parse(text); | 49 | let parse = SourceFile::parse(text); |
46 | let errors = parse.errors(); | 50 | let errors = parse.errors(); |
47 | assert!(!errors.is_empty(), "There should be errors in the file {:?}", path.display()); | 51 | assert_errors_are_present(&errors, path); |
48 | parse.debug_dump() | 52 | parse.debug_dump() |
49 | }); | 53 | }); |
50 | } | 54 | } |
@@ -76,7 +80,7 @@ fn self_hosting_parsing() { | |||
76 | .into_iter() | 80 | .into_iter() |
77 | .filter_entry(|entry| { | 81 | .filter_entry(|entry| { |
78 | !entry.path().components().any(|component| { | 82 | !entry.path().components().any(|component| { |
79 | // Get all files which are not in the crates/ra_syntax/tests/data folder | 83 | // Get all files which are not in the crates/ra_syntax/test_data folder |
80 | component == Component::Normal(OsStr::new("test_data")) | 84 | component == Component::Normal(OsStr::new("test_data")) |
81 | }) | 85 | }) |
82 | }) | 86 | }) |
@@ -102,15 +106,47 @@ fn test_data_dir() -> PathBuf { | |||
102 | project_dir().join("crates/ra_syntax/test_data") | 106 | project_dir().join("crates/ra_syntax/test_data") |
103 | } | 107 | } |
104 | 108 | ||
105 | fn dump_tokens(tokens: &[crate::Token], text: &str) -> String { | 109 | fn assert_errors_are_present(errors: &[SyntaxError], path: &Path) { |
110 | assert!(!errors.is_empty(), "There should be errors in the file {:?}", path.display()); | ||
111 | } | ||
112 | fn assert_errors_are_absent(errors: &[SyntaxError], path: &Path) { | ||
113 | assert_eq!( | ||
114 | errors, | ||
115 | &[] as &[SyntaxError], | ||
116 | "There should be no errors in the file {:?}", | ||
117 | path.display(), | ||
118 | ); | ||
119 | } | ||
120 | |||
121 | fn dump_tokens_and_errors(tokens: &[Token], errors: &[SyntaxError], text: &str) -> String { | ||
106 | let mut acc = String::new(); | 122 | let mut acc = String::new(); |
107 | let mut offset = 0; | 123 | let mut offset = 0; |
108 | for token in tokens { | 124 | for token in tokens { |
109 | let len: u32 = token.len.into(); | 125 | let token_len = token.len.to_usize(); |
110 | let len = len as usize; | 126 | let token_text = &text[offset..offset + token_len]; |
111 | let token_text = &text[offset..offset + len]; | 127 | offset += token_len; |
112 | offset += len; | 128 | writeln!(acc, "{:?} {} {:?}", token.kind, token_len, token_text).unwrap(); |
113 | write!(acc, "{:?} {} {:?}\n", token.kind, token.len, token_text).unwrap() | 129 | } |
130 | for err in errors { | ||
131 | let err_range = location_to_range(err.location()); | ||
132 | writeln!( | ||
133 | acc, | ||
134 | "> error{:?} token({:?}) msg({})", | ||
135 | err.location(), | ||
136 | &text[err_range], | ||
137 | err.kind() | ||
138 | ) | ||
139 | .unwrap(); | ||
140 | } | ||
141 | return acc; | ||
142 | |||
143 | // FIXME: copy-pasted this from `ra_ide/src/diagnostics.rs` | ||
144 | // `Location` will be refactored soon in new PR, see todos here: | ||
145 | // https://github.com/rust-analyzer/rust-analyzer/issues/223 | ||
146 | fn location_to_range(location: Location) -> TextRange { | ||
147 | match location { | ||
148 | Location::Offset(offset) => TextRange::offset_len(offset, 1.into()), | ||
149 | Location::Range(range) => range, | ||
150 | } | ||
114 | } | 151 | } |
115 | acc | ||
116 | } | 152 | } |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 445e3b3e4..8a5f0e4b7 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -94,6 +94,12 @@ impl From<rustc_lexer::unescape::EscapeError> for SyntaxErrorKind { | |||
94 | } | 94 | } |
95 | 95 | ||
96 | pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | 96 | pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { |
97 | // FIXME: | ||
98 | // * Add validation of character literal containing only a single char | ||
99 | // * Add validation of `crate` keyword not appearing in the middle of the symbol path | ||
100 | // * Add validation of doc comments are being attached to nodes | ||
101 | // * Remove validation of unterminated literals (it is already implemented in `tokenize()`) | ||
102 | |||
97 | let mut errors = Vec::new(); | 103 | let mut errors = Vec::new(); |
98 | for node in root.descendants() { | 104 | for node in root.descendants() { |
99 | match_ast! { | 105 | match_ast! { |