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/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
4 files changed, 120 insertions, 0 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 @@
1SOURCE_FILE@0..83
2 USE_ITEM@0..12
3 USE_KW@0..3 "use"
4 WHITESPACE@3..4 " "
5 USE_TREE@4..11
6 PATH@4..11
7 PATH_SEGMENT@4..11
8 COLON2@4..6 "::"
9 CRATE_KW@6..11 "crate"
10 SEMICOLON@11..12 ";"
11 WHITESPACE@12..13 "\n"
12 USE_ITEM@13..39
13 USE_KW@13..16 "use"
14 WHITESPACE@16..17 " "
15 USE_TREE@17..38
16 USE_TREE_LIST@17..38
17 L_CURLY@17..18 "{"
18 USE_TREE@18..23
19 PATH@18..23
20 PATH_SEGMENT@18..23
21 CRATE_KW@18..23 "crate"
22 COMMA@23..24 ","
23 WHITESPACE@24..25 " "
24 USE_TREE@25..37
25 PATH@25..28
26 PATH_SEGMENT@25..28
27 NAME_REF@25..28
28 IDENT@25..28 "foo"
29 COLON2@28..30 "::"
30 USE_TREE_LIST@30..37
31 L_CURLY@30..31 "{"
32 USE_TREE@31..36
33 PATH@31..36
34 PATH_SEGMENT@31..36
35 CRATE_KW@31..36 "crate"
36 R_CURLY@36..37 "}"
37 R_CURLY@37..38 "}"
38 SEMICOLON@38..39 ";"
39 WHITESPACE@39..40 "\n"
40 USE_ITEM@40..57
41 USE_KW@40..43 "use"
42 WHITESPACE@43..44 " "
43 USE_TREE@44..56
44 PATH@44..56
45 PATH@44..49
46 PATH_SEGMENT@44..49
47 NAME_REF@44..49
48 IDENT@44..49 "hello"
49 COLON2@49..51 "::"
50 PATH_SEGMENT@51..56
51 CRATE_KW@51..56 "crate"
52 SEMICOLON@56..57 ";"
53 WHITESPACE@57..58 "\n"
54 USE_ITEM@58..82
55 USE_KW@58..61 "use"
56 WHITESPACE@61..62 " "
57 USE_TREE@62..81
58 PATH@62..81
59 PATH@62..74
60 PATH@62..67
61 PATH_SEGMENT@62..67
62 NAME_REF@62..67
63 IDENT@62..67 "hello"
64 COLON2@67..69 "::"
65 PATH_SEGMENT@69..74
66 CRATE_KW@69..74 "crate"
67 COLON2@74..76 "::"
68 PATH_SEGMENT@76..81
69 NAME_REF@76..81
70 IDENT@76..81 "there"
71 SEMICOLON@81..82 ";"
72 WHITESPACE@82..83 "\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;