aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src')
-rw-r--r--crates/ra_syntax/src/tests.rs80
-rw-r--r--crates/ra_syntax/src/validation.rs6
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 @@
1use std::{ 1use std::{
2 fmt::Write, 2 fmt::Write,
3 path::{Component, PathBuf}, 3 path::{Component, Path, PathBuf},
4}; 4};
5 5
6use test_utils::{collect_tests, dir_tests, project_dir, read_text}; 6use test_utils::{collect_tests, dir_tests, project_dir, read_text};
7 7
8use crate::{fuzz, SourceFile}; 8use crate::{fuzz, tokenize, Location, SourceFile, SyntaxError, TextRange, Token};
9 9
10#[test] 10#[test]
11fn lexer_tests() { 11fn 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
105fn dump_tokens(tokens: &[crate::Token], text: &str) -> String { 109fn assert_errors_are_present(errors: &[SyntaxError], path: &Path) {
110 assert!(!errors.is_empty(), "There should be errors in the file {:?}", path.display());
111}
112fn 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
121fn 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
96pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { 96pub(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! {