diff options
Diffstat (limited to 'crates/ra_syntax')
-rw-r--r-- | crates/ra_syntax/src/ast/edit.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/make.rs | 71 | ||||
-rw-r--r-- | crates/ra_syntax/src/syntax_error.rs | 4 | ||||
-rw-r--r-- | crates/ra_syntax/src/validation.rs | 23 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.txt | 99 |
6 files changed, 174 insertions, 31 deletions
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 47bdbb81a..6f005a2d8 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -358,7 +358,7 @@ fn replace_children<N: AstNode>( | |||
358 | fn test_increase_indent() { | 358 | fn test_increase_indent() { |
359 | let arm_list = { | 359 | let arm_list = { |
360 | let arm = make::match_arm(iter::once(make::placeholder_pat().into()), make::expr_unit()); | 360 | let arm = make::match_arm(iter::once(make::placeholder_pat().into()), make::expr_unit()); |
361 | make::match_arm_list(vec![arm.clone(), arm].into_iter()) | 361 | make::match_arm_list(vec![arm.clone(), arm]) |
362 | }; | 362 | }; |
363 | assert_eq!( | 363 | assert_eq!( |
364 | arm_list.syntax().to_string(), | 364 | arm_list.syntax().to_string(), |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 95062ef6c..9749327fa 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -4,6 +4,10 @@ use itertools::Itertools; | |||
4 | 4 | ||
5 | use crate::{ast, AstNode, SourceFile}; | 5 | use crate::{ast, AstNode, SourceFile}; |
6 | 6 | ||
7 | pub fn name(text: &str) -> ast::Name { | ||
8 | ast_from_text(&format!("mod {};", text)) | ||
9 | } | ||
10 | |||
7 | pub fn name_ref(text: &str) -> ast::NameRef { | 11 | pub fn name_ref(text: &str) -> ast::NameRef { |
8 | ast_from_text(&format!("fn f() {{ {}; }}", text)) | 12 | ast_from_text(&format!("fn f() {{ {}; }}", text)) |
9 | } | 13 | } |
@@ -43,6 +47,21 @@ pub fn expr_unit() -> ast::Expr { | |||
43 | pub fn expr_unimplemented() -> ast::Expr { | 47 | pub fn expr_unimplemented() -> ast::Expr { |
44 | expr_from_text("unimplemented!()") | 48 | expr_from_text("unimplemented!()") |
45 | } | 49 | } |
50 | pub fn expr_path(path: ast::Path) -> ast::Expr { | ||
51 | expr_from_text(&path.syntax().to_string()) | ||
52 | } | ||
53 | pub fn expr_continue() -> ast::Expr { | ||
54 | expr_from_text("continue") | ||
55 | } | ||
56 | pub fn expr_break() -> ast::Expr { | ||
57 | expr_from_text("break") | ||
58 | } | ||
59 | pub fn expr_return() -> ast::Expr { | ||
60 | expr_from_text("return") | ||
61 | } | ||
62 | pub fn expr_match(expr: ast::Expr, match_arm_list: ast::MatchArmList) -> ast::Expr { | ||
63 | expr_from_text(&format!("match {} {}", expr.syntax(), match_arm_list.syntax())) | ||
64 | } | ||
46 | fn expr_from_text(text: &str) -> ast::Expr { | 65 | fn expr_from_text(text: &str) -> ast::Expr { |
47 | ast_from_text(&format!("const C: () = {};", text)) | 66 | ast_from_text(&format!("const C: () = {};", text)) |
48 | } | 67 | } |
@@ -65,9 +84,9 @@ pub fn placeholder_pat() -> ast::PlaceholderPat { | |||
65 | 84 | ||
66 | pub fn tuple_struct_pat( | 85 | pub fn tuple_struct_pat( |
67 | path: ast::Path, | 86 | path: ast::Path, |
68 | pats: impl Iterator<Item = ast::Pat>, | 87 | pats: impl IntoIterator<Item = ast::Pat>, |
69 | ) -> ast::TupleStructPat { | 88 | ) -> ast::TupleStructPat { |
70 | let pats_str = pats.map(|p| p.syntax().to_string()).join(", "); | 89 | let pats_str = pats.into_iter().map(|p| p.syntax().to_string()).join(", "); |
71 | return from_text(&format!("{}({})", path.syntax(), pats_str)); | 90 | return from_text(&format!("{}({})", path.syntax(), pats_str)); |
72 | 91 | ||
73 | fn from_text(text: &str) -> ast::TupleStructPat { | 92 | fn from_text(text: &str) -> ast::TupleStructPat { |
@@ -75,8 +94,8 @@ pub fn tuple_struct_pat( | |||
75 | } | 94 | } |
76 | } | 95 | } |
77 | 96 | ||
78 | pub fn record_pat(path: ast::Path, pats: impl Iterator<Item = ast::Pat>) -> ast::RecordPat { | 97 | pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) -> ast::RecordPat { |
79 | let pats_str = pats.map(|p| p.syntax().to_string()).join(", "); | 98 | let pats_str = pats.into_iter().map(|p| p.syntax().to_string()).join(", "); |
80 | return from_text(&format!("{} {{ {} }}", path.syntax(), pats_str)); | 99 | return from_text(&format!("{} {{ {} }}", path.syntax(), pats_str)); |
81 | 100 | ||
82 | fn from_text(text: &str) -> ast::RecordPat { | 101 | fn from_text(text: &str) -> ast::RecordPat { |
@@ -92,8 +111,8 @@ pub fn path_pat(path: ast::Path) -> ast::PathPat { | |||
92 | } | 111 | } |
93 | } | 112 | } |
94 | 113 | ||
95 | pub fn match_arm(pats: impl Iterator<Item = ast::Pat>, expr: ast::Expr) -> ast::MatchArm { | 114 | pub fn match_arm(pats: impl IntoIterator<Item = ast::Pat>, expr: ast::Expr) -> ast::MatchArm { |
96 | let pats_str = pats.map(|p| p.syntax().to_string()).join(" | "); | 115 | let pats_str = pats.into_iter().map(|p| p.syntax().to_string()).join(" | "); |
97 | return from_text(&format!("{} => {}", pats_str, expr.syntax())); | 116 | return from_text(&format!("{} => {}", pats_str, expr.syntax())); |
98 | 117 | ||
99 | fn from_text(text: &str) -> ast::MatchArm { | 118 | fn from_text(text: &str) -> ast::MatchArm { |
@@ -101,8 +120,8 @@ pub fn match_arm(pats: impl Iterator<Item = ast::Pat>, expr: ast::Expr) -> ast:: | |||
101 | } | 120 | } |
102 | } | 121 | } |
103 | 122 | ||
104 | pub fn match_arm_list(arms: impl Iterator<Item = ast::MatchArm>) -> ast::MatchArmList { | 123 | pub fn match_arm_list(arms: impl IntoIterator<Item = ast::MatchArm>) -> ast::MatchArmList { |
105 | let arms_str = arms.map(|arm| format!("\n {}", arm.syntax())).join(","); | 124 | let arms_str = arms.into_iter().map(|arm| format!("\n {}", arm.syntax())).join(","); |
106 | return from_text(&format!("{},\n", arms_str)); | 125 | return from_text(&format!("{},\n", arms_str)); |
107 | 126 | ||
108 | fn from_text(text: &str) -> ast::MatchArmList { | 127 | fn from_text(text: &str) -> ast::MatchArmList { |
@@ -110,25 +129,11 @@ pub fn match_arm_list(arms: impl Iterator<Item = ast::MatchArm>) -> ast::MatchAr | |||
110 | } | 129 | } |
111 | } | 130 | } |
112 | 131 | ||
113 | pub fn let_match_early(expr: ast::Expr, path: &str, early_expression: &str) -> ast::LetStmt { | 132 | pub fn where_pred( |
114 | return from_text(&format!( | 133 | path: ast::Path, |
115 | r#"let {} = match {} {{ | 134 | bounds: impl IntoIterator<Item = ast::TypeBound>, |
116 | {}(it) => it, | 135 | ) -> ast::WherePred { |
117 | None => {}, | 136 | let bounds = bounds.into_iter().map(|b| b.syntax().to_string()).join(" + "); |
118 | }};"#, | ||
119 | expr.syntax().text(), | ||
120 | expr.syntax().text(), | ||
121 | path, | ||
122 | early_expression | ||
123 | )); | ||
124 | |||
125 | fn from_text(text: &str) -> ast::LetStmt { | ||
126 | ast_from_text(&format!("fn f() {{ {} }}", text)) | ||
127 | } | ||
128 | } | ||
129 | |||
130 | pub fn where_pred(path: ast::Path, bounds: impl Iterator<Item = ast::TypeBound>) -> ast::WherePred { | ||
131 | let bounds = bounds.map(|b| b.syntax().to_string()).join(" + "); | ||
132 | return from_text(&format!("{}: {}", path.syntax(), bounds)); | 137 | return from_text(&format!("{}: {}", path.syntax(), bounds)); |
133 | 138 | ||
134 | fn from_text(text: &str) -> ast::WherePred { | 139 | fn from_text(text: &str) -> ast::WherePred { |
@@ -136,8 +141,8 @@ pub fn where_pred(path: ast::Path, bounds: impl Iterator<Item = ast::TypeBound>) | |||
136 | } | 141 | } |
137 | } | 142 | } |
138 | 143 | ||
139 | pub fn where_clause(preds: impl Iterator<Item = ast::WherePred>) -> ast::WhereClause { | 144 | pub fn where_clause(preds: impl IntoIterator<Item = ast::WherePred>) -> ast::WhereClause { |
140 | let preds = preds.map(|p| p.syntax().to_string()).join(", "); | 145 | let preds = preds.into_iter().map(|p| p.syntax().to_string()).join(", "); |
141 | return from_text(preds.as_str()); | 146 | return from_text(preds.as_str()); |
142 | 147 | ||
143 | fn from_text(text: &str) -> ast::WhereClause { | 148 | fn from_text(text: &str) -> ast::WhereClause { |
@@ -153,6 +158,14 @@ pub fn if_expression(condition: &ast::Expr, statement: &str) -> ast::IfExpr { | |||
153 | )) | 158 | )) |
154 | } | 159 | } |
155 | 160 | ||
161 | pub fn let_stmt(pattern: ast::Pat, initializer: Option<ast::Expr>) -> ast::LetStmt { | ||
162 | let text = match initializer { | ||
163 | Some(it) => format!("let {} = {};", pattern.syntax(), it.syntax()), | ||
164 | None => format!("let {};", pattern.syntax()), | ||
165 | }; | ||
166 | ast_from_text(&format!("fn f() {{ {} }}", text)) | ||
167 | } | ||
168 | |||
156 | fn ast_from_text<N: AstNode>(text: &str) -> N { | 169 | fn ast_from_text<N: AstNode>(text: &str) -> N { |
157 | let parse = SourceFile::parse(text); | 170 | let parse = SourceFile::parse(text); |
158 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | 171 | let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); |
diff --git a/crates/ra_syntax/src/syntax_error.rs b/crates/ra_syntax/src/syntax_error.rs index d6eca2ad7..1f60a7aab 100644 --- a/crates/ra_syntax/src/syntax_error.rs +++ b/crates/ra_syntax/src/syntax_error.rs | |||
@@ -82,6 +82,7 @@ pub enum SyntaxErrorKind { | |||
82 | InvalidBlockAttr, | 82 | InvalidBlockAttr, |
83 | InvalidMatchInnerAttr, | 83 | InvalidMatchInnerAttr, |
84 | InvalidTupleIndexFormat, | 84 | InvalidTupleIndexFormat, |
85 | VisibilityNotAllowed, | ||
85 | } | 86 | } |
86 | 87 | ||
87 | impl fmt::Display for SyntaxErrorKind { | 88 | impl fmt::Display for SyntaxErrorKind { |
@@ -99,6 +100,9 @@ impl fmt::Display for SyntaxErrorKind { | |||
99 | } | 100 | } |
100 | ParseError(msg) => write!(f, "{}", msg.0), | 101 | ParseError(msg) => write!(f, "{}", msg.0), |
101 | EscapeError(err) => write!(f, "{}", err), | 102 | EscapeError(err) => write!(f, "{}", err), |
103 | VisibilityNotAllowed => { | ||
104 | write!(f, "unnecessary visibility qualifier") | ||
105 | } | ||
102 | } | 106 | } |
103 | } | 107 | } |
104 | } | 108 | } |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index ab4f15908..2d596763e 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -6,7 +6,7 @@ use rustc_lexer::unescape; | |||
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | ast, match_ast, AstNode, SyntaxError, SyntaxErrorKind, | 8 | ast, match_ast, AstNode, SyntaxError, SyntaxErrorKind, |
9 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, INT_NUMBER, STRING}, | 9 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST_DEF, FN_DEF, INT_NUMBER, STRING, TYPE_ALIAS_DEF}, |
10 | SyntaxNode, SyntaxToken, TextUnit, T, | 10 | SyntaxNode, SyntaxToken, TextUnit, T, |
11 | }; | 11 | }; |
12 | 12 | ||
@@ -102,6 +102,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | |||
102 | ast::BlockExpr(it) => { block::validate_block_expr(it, &mut errors) }, | 102 | ast::BlockExpr(it) => { block::validate_block_expr(it, &mut errors) }, |
103 | ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, | 103 | ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, |
104 | ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, | 104 | ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, |
105 | ast::Visibility(it) => { validate_visibility(it, &mut errors) }, | ||
105 | _ => (), | 106 | _ => (), |
106 | } | 107 | } |
107 | } | 108 | } |
@@ -206,3 +207,23 @@ fn validate_numeric_name(name_ref: Option<ast::NameRef>, errors: &mut Vec<Syntax | |||
206 | name_ref?.syntax().first_child_or_token()?.into_token().filter(|it| it.kind() == INT_NUMBER) | 207 | name_ref?.syntax().first_child_or_token()?.into_token().filter(|it| it.kind() == INT_NUMBER) |
207 | } | 208 | } |
208 | } | 209 | } |
210 | |||
211 | fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) { | ||
212 | let parent = match vis.syntax().parent() { | ||
213 | Some(it) => it, | ||
214 | None => return, | ||
215 | }; | ||
216 | match parent.kind() { | ||
217 | FN_DEF | CONST_DEF | TYPE_ALIAS_DEF => (), | ||
218 | _ => return, | ||
219 | } | ||
220 | let impl_block = match parent.parent().and_then(|it| it.parent()).and_then(ast::ImplBlock::cast) | ||
221 | { | ||
222 | Some(it) => it, | ||
223 | None => return, | ||
224 | }; | ||
225 | if impl_block.target_trait().is_some() { | ||
226 | errors | ||
227 | .push(SyntaxError::new(SyntaxErrorKind::VisibilityNotAllowed, vis.syntax.text_range())) | ||
228 | } | ||
229 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rs b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rs new file mode 100644 index 000000000..a43e7ef10 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rs | |||
@@ -0,0 +1,6 @@ | |||
1 | impl T for () { | ||
2 | fn foo() {} | ||
3 | pub fn bar() {} | ||
4 | pub(crate) type Baz = (); | ||
5 | pub(crate) const C: i32 = 92; | ||
6 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.txt b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.txt new file mode 100644 index 000000000..749c8cddb --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.txt | |||
@@ -0,0 +1,99 @@ | |||
1 | SOURCE_FILE@[0; 118) | ||
2 | IMPL_BLOCK@[0; 117) | ||
3 | IMPL_KW@[0; 4) "impl" | ||
4 | WHITESPACE@[4; 5) " " | ||
5 | PATH_TYPE@[5; 6) | ||
6 | PATH@[5; 6) | ||
7 | PATH_SEGMENT@[5; 6) | ||
8 | NAME_REF@[5; 6) | ||
9 | IDENT@[5; 6) "T" | ||
10 | WHITESPACE@[6; 7) " " | ||
11 | FOR_KW@[7; 10) "for" | ||
12 | WHITESPACE@[10; 11) " " | ||
13 | TUPLE_TYPE@[11; 13) | ||
14 | L_PAREN@[11; 12) "(" | ||
15 | R_PAREN@[12; 13) ")" | ||
16 | WHITESPACE@[13; 14) " " | ||
17 | ITEM_LIST@[14; 117) | ||
18 | L_CURLY@[14; 15) "{" | ||
19 | WHITESPACE@[15; 20) "\n " | ||
20 | FN_DEF@[20; 31) | ||
21 | FN_KW@[20; 22) "fn" | ||
22 | WHITESPACE@[22; 23) " " | ||
23 | NAME@[23; 26) | ||
24 | IDENT@[23; 26) "foo" | ||
25 | PARAM_LIST@[26; 28) | ||
26 | L_PAREN@[26; 27) "(" | ||
27 | R_PAREN@[27; 28) ")" | ||
28 | WHITESPACE@[28; 29) " " | ||
29 | BLOCK_EXPR@[29; 31) | ||
30 | BLOCK@[29; 31) | ||
31 | L_CURLY@[29; 30) "{" | ||
32 | R_CURLY@[30; 31) "}" | ||
33 | WHITESPACE@[31; 36) "\n " | ||
34 | FN_DEF@[36; 51) | ||
35 | VISIBILITY@[36; 39) | ||
36 | PUB_KW@[36; 39) "pub" | ||
37 | WHITESPACE@[39; 40) " " | ||
38 | FN_KW@[40; 42) "fn" | ||
39 | WHITESPACE@[42; 43) " " | ||
40 | NAME@[43; 46) | ||
41 | IDENT@[43; 46) "bar" | ||
42 | PARAM_LIST@[46; 48) | ||
43 | L_PAREN@[46; 47) "(" | ||
44 | R_PAREN@[47; 48) ")" | ||
45 | WHITESPACE@[48; 49) " " | ||
46 | BLOCK_EXPR@[49; 51) | ||
47 | BLOCK@[49; 51) | ||
48 | L_CURLY@[49; 50) "{" | ||
49 | R_CURLY@[50; 51) "}" | ||
50 | WHITESPACE@[51; 56) "\n " | ||
51 | TYPE_ALIAS_DEF@[56; 81) | ||
52 | VISIBILITY@[56; 66) | ||
53 | PUB_KW@[56; 59) "pub" | ||
54 | L_PAREN@[59; 60) "(" | ||
55 | CRATE_KW@[60; 65) "crate" | ||
56 | R_PAREN@[65; 66) ")" | ||
57 | WHITESPACE@[66; 67) " " | ||
58 | TYPE_KW@[67; 71) "type" | ||
59 | WHITESPACE@[71; 72) " " | ||
60 | NAME@[72; 75) | ||
61 | IDENT@[72; 75) "Baz" | ||
62 | WHITESPACE@[75; 76) " " | ||
63 | EQ@[76; 77) "=" | ||
64 | WHITESPACE@[77; 78) " " | ||
65 | TUPLE_TYPE@[78; 80) | ||
66 | L_PAREN@[78; 79) "(" | ||
67 | R_PAREN@[79; 80) ")" | ||
68 | SEMI@[80; 81) ";" | ||
69 | WHITESPACE@[81; 86) "\n " | ||
70 | CONST_DEF@[86; 115) | ||
71 | VISIBILITY@[86; 96) | ||
72 | PUB_KW@[86; 89) "pub" | ||
73 | L_PAREN@[89; 90) "(" | ||
74 | CRATE_KW@[90; 95) "crate" | ||
75 | R_PAREN@[95; 96) ")" | ||
76 | WHITESPACE@[96; 97) " " | ||
77 | CONST_KW@[97; 102) "const" | ||
78 | WHITESPACE@[102; 103) " " | ||
79 | NAME@[103; 104) | ||
80 | IDENT@[103; 104) "C" | ||
81 | COLON@[104; 105) ":" | ||
82 | WHITESPACE@[105; 106) " " | ||
83 | PATH_TYPE@[106; 109) | ||
84 | PATH@[106; 109) | ||
85 | PATH_SEGMENT@[106; 109) | ||
86 | NAME_REF@[106; 109) | ||
87 | IDENT@[106; 109) "i32" | ||
88 | WHITESPACE@[109; 110) " " | ||
89 | EQ@[110; 111) "=" | ||
90 | WHITESPACE@[111; 112) " " | ||
91 | LITERAL@[112; 114) | ||
92 | INT_NUMBER@[112; 114) "92" | ||
93 | SEMI@[114; 115) ";" | ||
94 | WHITESPACE@[115; 116) "\n" | ||
95 | R_CURLY@[116; 117) "}" | ||
96 | WHITESPACE@[117; 118) "\n" | ||
97 | error [36; 39): unnecessary visibility qualifier | ||
98 | error [56; 66): unnecessary visibility qualifier | ||
99 | error [86; 96): unnecessary visibility qualifier | ||