aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs1
-rw-r--r--crates/ra_syntax/src/validation.rs39
-rw-r--r--crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast76
-rw-r--r--crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs4
-rw-r--r--xtask/src/ast_src.rs2
5 files changed, 121 insertions, 1 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}
1250impl PathSegment { 1250impl 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..a30bc97bb 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,41 @@ fn validate_range_expr(expr: ast::RangeExpr, errors: &mut Vec<SyntaxError>) {
222 )); 223 ));
223 } 224 }
224} 225}
226
227fn 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 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 // We now know that the path variable describes a complete path.
246 // For expressions and types, validation is complete, but we still have
247 // to handle UseItems like this:
248 // use foo:{crate};
249 // so we crawl upwards looking for any preceding paths on `UseTree`s
250 for node in path.syntax().ancestors().skip(1) {
251 match_ast! {
252 match node {
253 ast::UseTree(it) => if let Some(tree_path) = it.path() {
254 if tree_path != path {
255 errors.push(SyntaxError::new(ERR_MSG, crate_token.text_range()));
256 }
257 },
258 ast::UseTreeList(_it) => continue,
259 _ => return,
260 }
261 };
262 }
263}
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..8306f7361
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rast
@@ -0,0 +1,76 @@
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] "crate"
36 [email protected] "}"
37 [email protected] "}"
38 [email protected] ";"
39 [email protected] "\n"
40 [email protected]
41 [email protected] "use"
42 [email protected] " "
43 [email protected]
44 [email protected]
45 [email protected]
46 [email protected]
47 [email protected]
48 [email protected] "hello"
49 [email protected] "::"
50 [email protected]
51 [email protected] "crate"
52 [email protected] ";"
53 [email protected] "\n"
54 [email protected]
55 [email protected] "use"
56 [email protected] " "
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]
69 [email protected]
70 [email protected] "there"
71 [email protected] ";"
72 [email protected] "\n"
73error 6..11: The `crate` keyword is only allowed as the first segment of a path
74error 31..36: The `crate` keyword is only allowed as the first segment of a path
75error 51..56: The `crate` keyword is only allowed as the first segment of a path
76error 69..74: 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..bead4c0b6
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/err/0040_illegal_crate_kw_location.rs
@@ -0,0 +1,4 @@
1use ::crate;
2use {crate, foo::{crate}};
3use hello::crate;
4use hello::crate::there;
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs
index 9c02f7c6f..98c8644e4 100644
--- a/xtask/src/ast_src.rs
+++ b/xtask/src/ast_src.rs
@@ -595,7 +595,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
595 qualifier: Path, 595 qualifier: Path,
596 } 596 }
597 struct PathSegment { 597 struct PathSegment {
598 T![::], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>] 598 T![::], T![crate], T![<], NameRef, TypeArgList, ParamList, RetType, PathType, T![>]
599 } 599 }
600 struct TypeArgList { 600 struct TypeArgList {
601 T![::], 601 T![::],