diff options
Diffstat (limited to 'crates/ra_syntax')
10 files changed, 244 insertions, 25 deletions
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 2cb3ad011..3b5e05af9 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs | |||
@@ -1249,6 +1249,7 @@ pub struct PathSegment { | |||
1249 | } | 1249 | } |
1250 | impl PathSegment { | 1250 | impl PathSegment { |
1251 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } | 1251 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } |
1252 | pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } | ||
1252 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | 1253 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } |
1253 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | 1254 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } |
1254 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } | 1255 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index 5e93895ec..f0b3dec63 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -96,6 +96,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | |||
96 | ast::RecordField(it) => validate_numeric_name(it.name_ref(), &mut errors), | 96 | ast::RecordField(it) => validate_numeric_name(it.name_ref(), &mut errors), |
97 | ast::Visibility(it) => validate_visibility(it, &mut errors), | 97 | ast::Visibility(it) => validate_visibility(it, &mut errors), |
98 | ast::RangeExpr(it) => validate_range_expr(it, &mut errors), | 98 | ast::RangeExpr(it) => validate_range_expr(it, &mut errors), |
99 | ast::PathSegment(it) => validate_crate_keyword_in_path_segment(it, &mut errors), | ||
99 | _ => (), | 100 | _ => (), |
100 | } | 101 | } |
101 | } | 102 | } |
@@ -222,3 +223,60 @@ fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) { | |||
222 | )); | 223 | )); |
223 | } | 224 | } |
224 | } | 225 | } |
226 | |||
227 | fn validate_crate_keyword_in_path_segment( | ||
228 | segment: ast::PathSegment, | ||
229 | errors: &mut Vec<SyntaxError>, | ||
230 | ) { | ||
231 | const ERR_MSG: &str = "The `crate` keyword is only allowed as the first segment of a path"; | ||
232 | |||
233 | let crate_token = match segment.crate_token() { | ||
234 | None => return, | ||
235 | Some(it) => it, | ||
236 | }; | ||
237 | |||
238 | // Disallow both ::crate and foo::crate | ||
239 | let mut path = segment.parent_path(); | ||
240 | if segment.coloncolon_token().is_some() || path.qualifier().is_some() { | ||
241 | errors.push(SyntaxError::new(ERR_MSG, crate_token.text_range())); | ||
242 | return; | ||
243 | } | ||
244 | |||
245 | // For expressions and types, validation is complete, but we still have | ||
246 | // to handle invalid UseItems like this: | ||
247 | // | ||
248 | // use foo:{crate::bar::baz}; | ||
249 | // | ||
250 | // To handle this we must inspect the parent `UseItem`s and `UseTree`s | ||
251 | // but right now we're looking deep inside the nested `Path` nodes because | ||
252 | // `Path`s are left-associative: | ||
253 | // | ||
254 | // ((crate)::bar)::baz) | ||
255 | // ^ current value of path | ||
256 | // | ||
257 | // So we need to climb to the top | ||
258 | while let Some(parent) = path.parent_path() { | ||
259 | path = parent; | ||
260 | } | ||
261 | |||
262 | // Now that we've found the whole path we need to see if there's a prefix | ||
263 | // somewhere in the UseTree hierarchy. This check is arbitrarily deep | ||
264 | // because rust allows arbitrary nesting like so: | ||
265 | // | ||
266 | // use {foo::{{{{crate::bar::baz}}}}}; | ||
267 | for node in path.syntax().ancestors().skip(1) { | ||
268 | match_ast! { | ||
269 | match node { | ||
270 | ast::UseTree(it) => if let Some(tree_path) = it.path() { | ||
271 | // Even a top-level path exists within a `UseTree` so we must explicitly | ||
272 | // allow our path but disallow anything else | ||
273 | if tree_path != path { | ||
274 | errors.push(SyntaxError::new(ERR_MSG, crate_token.text_range())); | ||
275 | } | ||
276 | }, | ||
277 | ast::UseTreeList(_it) => continue, | ||
278 | _ => return, | ||
279 | } | ||
280 | }; | ||
281 | } | ||
282 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast b/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast new file mode 100644 index 000000000..d2a549273 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast | |||
@@ -0,0 +1,91 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "use" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] | ||
7 | [email protected] | ||
8 | [email protected] "::" | ||
9 | [email protected] "crate" | ||
10 | [email protected] ";" | ||
11 | [email protected] "\n" | ||
12 | [email protected] | ||
13 | [email protected] "use" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] "{" | ||
18 | [email protected] | ||
19 | [email protected] | ||
20 | [email protected] | ||
21 | [email protected] "crate" | ||
22 | [email protected] "," | ||
23 | [email protected] " " | ||
24 | [email protected] | ||
25 | [email protected] | ||
26 | [email protected] | ||
27 | [email protected] | ||
28 | [email protected] "foo" | ||
29 | [email protected] "::" | ||
30 | [email protected] | ||
31 | [email protected] "{" | ||
32 | [email protected] | ||
33 | [email protected] | ||
34 | [email protected] | ||
35 | [email protected] | ||
36 | [email protected] | ||
37 | [email protected] | ||
38 | [email protected] "crate" | ||
39 | [email protected] "::" | ||
40 | [email protected] | ||
41 | [email protected] | ||
42 | [email protected] "foo" | ||
43 | [email protected] "::" | ||
44 | [email protected] | ||
45 | [email protected] | ||
46 | [email protected] "bar" | ||
47 | [email protected] "::" | ||
48 | [email protected] | ||
49 | [email protected] | ||
50 | [email protected] "baz" | ||
51 | [email protected] "}" | ||
52 | [email protected] "}" | ||
53 | [email protected] ";" | ||
54 | [email protected] "\n" | ||
55 | [email protected] | ||
56 | [email protected] "use" | ||
57 | [email protected] " " | ||
58 | [email protected] | ||
59 | [email protected] | ||
60 | [email protected] | ||
61 | [email protected] | ||
62 | [email protected] | ||
63 | [email protected] "hello" | ||
64 | [email protected] "::" | ||
65 | [email protected] | ||
66 | [email protected] "crate" | ||
67 | [email protected] ";" | ||
68 | [email protected] "\n" | ||
69 | [email protected] | ||
70 | [email protected] "use" | ||
71 | [email protected] " " | ||
72 | [email protected] | ||
73 | [email protected] | ||
74 | [email protected] | ||
75 | [email protected] | ||
76 | [email protected] | ||
77 | [email protected] | ||
78 | [email protected] "hello" | ||
79 | [email protected] "::" | ||
80 | [email protected] | ||
81 | [email protected] "crate" | ||
82 | [email protected] "::" | ||
83 | [email protected] | ||
84 | [email protected] | ||
85 | [email protected] "there" | ||
86 | [email protected] ";" | ||
87 | [email protected] "\n" | ||
88 | error 6..11: The `crate` keyword is only allowed as the first segment of a path | ||
89 | error 31..36: The `crate` keyword is only allowed as the first segment of a path | ||
90 | error 66..71: The `crate` keyword is only allowed as the first segment of a path | ||
91 | error 84..89: The `crate` keyword is only allowed as the first segment of a path | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs b/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs new file mode 100644 index 000000000..508def2c7 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs | |||
@@ -0,0 +1,4 @@ | |||
1 | use ::crate; | ||
2 | use {crate, foo::{crate::foo::bar::baz}}; | ||
3 | use hello::crate; | ||
4 | use hello::crate::there; | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rast b/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rast index bd74b44a6..cf3a90400 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rast +++ b/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rast | |||
@@ -1,4 +1,4 @@ | |||
1 | [email protected]50 | 1 | [email protected]49 |
2 | [email protected] | 2 | [email protected] |
3 | [email protected] "use" | 3 | [email protected] "use" |
4 | [email protected] " " | 4 | [email protected] " " |
@@ -104,32 +104,33 @@ [email protected] | |||
104 | [email protected] " " | 104 | [email protected] " " |
105 | [email protected] "// Rust 2015" | 105 | [email protected] "// Rust 2015" |
106 | [email protected] "\n" | 106 | [email protected] "\n" |
107 | [email protected]6 | 107 | [email protected]5 |
108 | [email protected] "use" | 108 | [email protected] "use" |
109 | [email protected] " " | 109 | [email protected] " " |
110 | [email protected]5 | 110 | [email protected]4 |
111 | [email protected] "::" | 111 | [email protected] "::" |
112 | [email protected]5 | 112 | [email protected]4 |
113 | [email protected] "{" | 113 | [email protected] "{" |
114 | [email protected]4 | 114 | [email protected]3 |
115 | [email protected]4 | 115 | [email protected]3 |
116 | [email protected] "{" | 116 | [email protected] "{" |
117 | [email protected]3 | 117 | [email protected]2 |
118 | [email protected]3 | 118 | [email protected]2 |
119 | [email protected] "{" | 119 | [email protected] "{" |
120 | [email protected] | 120 | [email protected] |
121 | [email protected] | 121 | [email protected] |
122 | [email protected] | 122 | [email protected] |
123 | [email protected] | 123 | [email protected] |
124 | [email protected] "crate" | 124 | [email protected] |
125 | [email protected] "::" | 125 | [email protected] "root" |
126 | [email protected] | 126 | [email protected] "::" |
127 | [email protected] | 127 | [email protected] |
128 | [email protected] "export" | 128 | [email protected] |
129 | [email protected] "}" | 129 | [email protected] "export" |
130 | [email protected] "}" | 130 | [email protected] "}" |
131 | [email protected] "}" | 131 | [email protected] "}" |
132 | [email protected] ";" | 132 | [email protected] "}" |
133 | [email protected] " " | 133 | [email protected] ";" |
134 | [email protected] "// Nonsensical but pe ..." | 134 | [email protected] " " |
135 | [email protected] "\n" | 135 | [email protected] "// Nonsensical but pe ..." |
136 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rs b/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rs index 06c387cee..381cba1e2 100644 --- a/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rs +++ b/crates/ra_syntax/test_data/parser/inline/ok/0002_use_tree_list.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`) | 1 | use {crate::path::from::root, or::path::from::crate_name}; // Rust 2018 (with a crate named `or`) |
2 | use {path::from::root}; // Rust 2015 | 2 | use {path::from::root}; // Rust 2015 |
3 | use ::{some::arbritrary::path}; // Rust 2015 | 3 | use ::{some::arbritrary::path}; // Rust 2015 |
4 | use ::{{{crate::export}}}; // Nonsensical but perfectly legal nestnig | 4 | use ::{{{root::export}}}; // Nonsensical but perfectly legal nesting |
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast b/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast new file mode 100644 index 000000000..beb6d8010 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rast | |||
@@ -0,0 +1,35 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] "fn" | ||
4 | [email protected] " " | ||
5 | [email protected] | ||
6 | [email protected] "foo" | ||
7 | [email protected] | ||
8 | [email protected] "(" | ||
9 | [email protected] ")" | ||
10 | [email protected] " " | ||
11 | [email protected] | ||
12 | [email protected] | ||
13 | [email protected] "{" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] | ||
17 | [email protected] | ||
18 | [email protected] | ||
19 | [email protected] | ||
20 | [email protected] "try" | ||
21 | [email protected] "!" | ||
22 | [email protected] | ||
23 | [email protected] "(" | ||
24 | [email protected] "Ok" | ||
25 | [email protected] | ||
26 | [email protected] "(" | ||
27 | [email protected] | ||
28 | [email protected] "(" | ||
29 | [email protected] ")" | ||
30 | [email protected] ")" | ||
31 | [email protected] ")" | ||
32 | [email protected] ";" | ||
33 | [email protected] " " | ||
34 | [email protected] "}" | ||
35 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rs b/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rs new file mode 100644 index 000000000..61a6b46a0 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0159_try_macro_fallback.rs | |||
@@ -0,0 +1 @@ | |||
fn foo() { try!(Ok(())); } | |||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast b/crates/ra_syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast new file mode 100644 index 000000000..05b89d1c3 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0160_try_macro_rules.rast | |||
@@ -0,0 +1,27 @@ | |||
1 | [email protected] | ||
2 | [email protected] | ||
3 | [email protected] | ||
4 | [email protected] | ||
5 | [email protected] | ||
6 | [email protected] "macro_rules" | ||
7 | [email protected] "!" | ||
8 | [email protected] " " | ||
9 | [email protected] | ||
10 | [email protected] "try" | ||
11 | [email protected] " " | ||
12 | [email protected] | ||
13 | [email protected] "{" | ||
14 | [email protected] " " | ||
15 | [email protected] | ||
16 | [email protected] "(" | ||
17 | [email protected] ")" | ||
18 | [email protected] " " | ||
19 | [email protected] "=" | ||
20 | [email protected] ">" | ||
21 | [email protected] " " | ||
22 | [email protected] | ||
23 | [email protected] "{" | ||
24 | [email protected] "}" | ||
25 | [email protected] " " | ||
26 | [email protected] "}" | ||
27 | [email protected] "\n" | ||
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0160_try_macro_rules.rs b/crates/ra_syntax/test_data/parser/inline/ok/0160_try_macro_rules.rs new file mode 100644 index 000000000..2e2ab6e60 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/inline/ok/0160_try_macro_rules.rs | |||
@@ -0,0 +1 @@ | |||
macro_rules! try { () => {} } | |||