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.rs24
-rw-r--r--crates/ra_syntax/src/ast/make.rs6
-rw-r--r--crates/ra_syntax/src/ast/traits.rs19
-rw-r--r--crates/ra_syntax/src/lib.rs14
-rw-r--r--crates/ra_syntax/test_data/parser/err/0024_many_type_parens.txt91
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rs5
-rw-r--r--crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.txt101
7 files changed, 200 insertions, 60 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 1b2ce921a..a12da5be2 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -173,7 +173,7 @@ fn test_doc_comment_single_line_block_strips_suffix_whitespace() {
173 .ok() 173 .ok()
174 .unwrap(); 174 .unwrap();
175 let module = file.syntax().descendants().find_map(Module::cast).unwrap(); 175 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
176 assert_eq!("this is mod foo", module.doc_comment_text().unwrap()); 176 assert_eq!("this is mod foo ", module.doc_comment_text().unwrap());
177} 177}
178 178
179#[test] 179#[test]
@@ -191,7 +191,27 @@ fn test_doc_comment_multi_line_block_strips_suffix() {
191 .ok() 191 .ok()
192 .unwrap(); 192 .unwrap();
193 let module = file.syntax().descendants().find_map(Module::cast).unwrap(); 193 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
194 assert_eq!(" this\n is\n mod foo", module.doc_comment_text().unwrap()); 194 assert_eq!(
195 " this\n is\n mod foo\n ",
196 module.doc_comment_text().unwrap()
197 );
198}
199
200#[test]
201fn test_comments_preserve_trailing_whitespace() {
202 let file = SourceFile::parse(
203 r#"
204/// Representation of a Realm.
205/// In the specification these are called Realm Records.
206struct Realm {}"#,
207 )
208 .ok()
209 .unwrap();
210 let def = file.syntax().descendants().find_map(StructDef::cast).unwrap();
211 assert_eq!(
212 "Representation of a Realm. \nIn the specification these are called Realm Records.",
213 def.doc_comment_text().unwrap()
214 );
195} 215}
196 216
197#[test] 217#[test]
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs
index 00422ea91..3d5f18bfa 100644
--- a/crates/ra_syntax/src/ast/make.rs
+++ b/crates/ra_syntax/src/ast/make.rs
@@ -77,7 +77,7 @@ pub fn tuple_struct_pat(
77 77
78pub fn record_pat(path: ast::Path, pats: impl Iterator<Item = ast::Pat>) -> ast::RecordPat { 78pub fn record_pat(path: ast::Path, pats: impl Iterator<Item = ast::Pat>) -> ast::RecordPat {
79 let pats_str = pats.map(|p| p.syntax().to_string()).join(", "); 79 let pats_str = pats.map(|p| p.syntax().to_string()).join(", ");
80 return from_text(&format!("{}{{ {} }}", path.syntax(), pats_str)); 80 return from_text(&format!("{} {{ {} }}", path.syntax(), pats_str));
81 81
82 fn from_text(text: &str) -> ast::RecordPat { 82 fn from_text(text: &str) -> ast::RecordPat {
83 ast_from_text(&format!("fn f({}: ())", text)) 83 ast_from_text(&format!("fn f({}: ())", text))
@@ -129,11 +129,11 @@ pub fn where_clause(preds: impl Iterator<Item = ast::WherePred>) -> ast::WhereCl
129} 129}
130 130
131pub fn if_expression(condition: &ast::Expr, statement: &str) -> ast::IfExpr { 131pub fn if_expression(condition: &ast::Expr, statement: &str) -> ast::IfExpr {
132 return ast_from_text(&format!( 132 ast_from_text(&format!(
133 "fn f() {{ if !{} {{\n {}\n}}\n}}", 133 "fn f() {{ if !{} {{\n {}\n}}\n}}",
134 condition.syntax().text(), 134 condition.syntax().text(),
135 statement 135 statement
136 )); 136 ))
137} 137}
138 138
139fn ast_from_text<N: AstNode>(text: &str) -> N { 139fn ast_from_text<N: AstNode>(text: &str) -> N {
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
index f275a4955..c2b005886 100644
--- a/crates/ra_syntax/src/ast/traits.rs
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -6,6 +6,7 @@ use itertools::Itertools;
6 6
7use crate::{ 7use crate::{
8 ast::{self, child_opt, children, AstChildren, AstNode, AstToken}, 8 ast::{self, child_opt, children, AstChildren, AstNode, AstToken},
9 match_ast,
9 syntax_node::{SyntaxElementChildren, SyntaxNodeChildren}, 10 syntax_node::{SyntaxElementChildren, SyntaxNodeChildren},
10}; 11};
11 12
@@ -68,11 +69,12 @@ impl Iterator for ItemOrMacroIter {
68 fn next(&mut self) -> Option<ItemOrMacro> { 69 fn next(&mut self) -> Option<ItemOrMacro> {
69 loop { 70 loop {
70 let n = self.0.next()?; 71 let n = self.0.next()?;
71 if let Some(item) = ast::ModuleItem::cast(n.clone()) { 72 match_ast! {
72 return Some(ItemOrMacro::Item(item)); 73 match n {
73 } 74 ast::ModuleItem(it) => { return Some(ItemOrMacro::Item(it)) },
74 if let Some(call) = ast::MacroCall::cast(n) { 75 ast::MacroCall(it) => { return Some(ItemOrMacro::Macro(it)) },
75 return Some(ItemOrMacro::Macro(call)); 76 _ => {},
77 }
76 } 78 }
77 } 79 }
78 } 80 }
@@ -120,7 +122,7 @@ pub trait DocCommentsOwner: AstNode {
120 has_comments = true; 122 has_comments = true;
121 let prefix_len = comment.prefix().len(); 123 let prefix_len = comment.prefix().len();
122 124
123 let line = comment.text().as_str(); 125 let line: &str = comment.text().as_str();
124 126
125 // Determine if the prefix or prefix + 1 char is stripped 127 // Determine if the prefix or prefix + 1 char is stripped
126 let pos = 128 let pos =
@@ -136,7 +138,10 @@ pub trait DocCommentsOwner: AstNode {
136 line.len() 138 line.len()
137 }; 139 };
138 140
139 line[pos..end].trim_end().to_owned() 141 // Note that we do not trim the end of the line here
142 // since whitespace can have special meaning at the end
143 // of a line in markdown.
144 line[pos..end].to_owned()
140 }) 145 })
141 .join("\n"); 146 .join("\n");
142 147
diff --git a/crates/ra_syntax/src/lib.rs b/crates/ra_syntax/src/lib.rs
index c315ba552..5dcb6a95a 100644
--- a/crates/ra_syntax/src/lib.rs
+++ b/crates/ra_syntax/src/lib.rs
@@ -160,6 +160,20 @@ impl SourceFile {
160 } 160 }
161} 161}
162 162
163/// Matches a `SyntaxNode` against an `ast` type.
164///
165/// # Example:
166///
167/// ```ignore
168/// match_ast! {
169/// match node {
170/// ast::CallExpr(it) => { ... },
171/// ast::MethodCallExpr(it) => { ... },
172/// ast::MacroCall(it) => { ... },
173/// _ => None,
174/// }
175/// }
176/// ```
163#[macro_export] 177#[macro_export]
164macro_rules! match_ast { 178macro_rules! match_ast {
165 (match $node:ident { 179 (match $node:ident {
diff --git a/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.txt b/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.txt
index 198daf7b4..0a93e11a5 100644
--- a/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.txt
+++ b/crates/ra_syntax/test_data/parser/err/0024_many_type_parens.txt
@@ -179,50 +179,47 @@ SOURCE_FILE@[0; 240)
179 ERROR@[148; 149) 179 ERROR@[148; 149)
180 PLUS@[148; 149) "+" 180 PLUS@[148; 149) "+"
181 WHITESPACE@[149; 150) " " 181 WHITESPACE@[149; 150) " "
182 EXPR_STMT@[150; 151) 182 EXPR_STMT@[150; 180)
183 PAREN_EXPR@[150; 151) 183 TUPLE_EXPR@[150; 180)
184 L_PAREN@[150; 151) "(" 184 L_PAREN@[150; 151) "("
185 EXPR_STMT@[151; 157) 185 BIN_EXPR@[151; 180)
186 FOR_EXPR@[151; 157) 186 BIN_EXPR@[151; 178)
187 FOR_KW@[151; 154) "for" 187 BIN_EXPR@[151; 169)
188 ERROR@[154; 155) 188 BIN_EXPR@[151; 167)
189 L_ANGLE@[154; 155) "<" 189 BIN_EXPR@[151; 164)
190 ERROR@[155; 157) 190 FOR_EXPR@[151; 157)
191 LIFETIME@[155; 157) "\'a" 191 FOR_KW@[151; 154) "for"
192 EXPR_STMT@[157; 158) 192 ERROR@[154; 155)
193 ERROR@[157; 158) 193 L_ANGLE@[154; 155) "<"
194 R_ANGLE@[157; 158) ">" 194 ERROR@[155; 157)
195 WHITESPACE@[158; 159) " " 195 LIFETIME@[155; 157) "\'a"
196 EXPR_STMT@[159; 180) 196 R_ANGLE@[157; 158) ">"
197 BIN_EXPR@[159; 180) 197 WHITESPACE@[158; 159) " "
198 BIN_EXPR@[159; 178) 198 PATH_EXPR@[159; 164)
199 BIN_EXPR@[159; 169) 199 PATH@[159; 164)
200 BIN_EXPR@[159; 167) 200 PATH_SEGMENT@[159; 164)
201 PATH_EXPR@[159; 164) 201 NAME_REF@[159; 164)
202 PATH@[159; 164) 202 IDENT@[159; 164) "Trait"
203 PATH_SEGMENT@[159; 164) 203 L_ANGLE@[164; 165) "<"
204 NAME_REF@[159; 164) 204 ERROR@[165; 167)
205 IDENT@[159; 164) "Trait" 205 LIFETIME@[165; 167) "\'a"
206 L_ANGLE@[164; 165) "<" 206 R_ANGLE@[167; 168) ">"
207 ERROR@[165; 167) 207 ERROR@[168; 169)
208 LIFETIME@[165; 167) "\'a" 208 R_PAREN@[168; 169) ")"
209 R_ANGLE@[167; 168) ">" 209 WHITESPACE@[169; 170) " "
210 ERROR@[168; 169) 210 PLUS@[170; 171) "+"
211 R_PAREN@[168; 169) ")" 211 WHITESPACE@[171; 172) " "
212 WHITESPACE@[169; 170) " " 212 PAREN_EXPR@[172; 178)
213 PLUS@[170; 171) "+" 213 L_PAREN@[172; 173) "("
214 WHITESPACE@[171; 172) " " 214 PATH_EXPR@[173; 177)
215 PAREN_EXPR@[172; 178) 215 PATH@[173; 177)
216 L_PAREN@[172; 173) "(" 216 PATH_SEGMENT@[173; 177)
217 PATH_EXPR@[173; 177) 217 NAME_REF@[173; 177)
218 PATH@[173; 177) 218 IDENT@[173; 177) "Copy"
219 PATH_SEGMENT@[173; 177) 219 R_PAREN@[177; 178) ")"
220 NAME_REF@[173; 177) 220 R_ANGLE@[178; 179) ">"
221 IDENT@[173; 177) "Copy" 221 ERROR@[179; 180)
222 R_PAREN@[177; 178) ")" 222 SEMI@[179; 180) ";"
223 R_ANGLE@[178; 179) ">"
224 ERROR@[179; 180)
225 SEMI@[179; 180) ";"
226 WHITESPACE@[180; 185) "\n " 223 WHITESPACE@[180; 185) "\n "
227 LET_STMT@[185; 235) 224 LET_STMT@[185; 235)
228 LET_KW@[185; 188) "let" 225 LET_KW@[185; 188) "let"
@@ -307,18 +304,16 @@ error 146: expected expression
307error 147: expected SEMI 304error 147: expected SEMI
308error 148: expected expression 305error 148: expected expression
309error 149: expected SEMI 306error 149: expected SEMI
310error 151: expected expression
311error 151: expected R_PAREN
312error 151: expected SEMI
313error 154: expected pattern 307error 154: expected pattern
314error 155: expected IN_KW 308error 155: expected IN_KW
315error 155: expected expression 309error 155: expected expression
316error 157: expected a block 310error 157: expected a block
317error 157: expected expression
318error 158: expected SEMI
319error 165: expected expression 311error 165: expected expression
320error 168: expected expression 312error 168: expected expression
321error 179: expected expression 313error 179: expected expression
314error 180: expected COMMA
315error 180: expected expression
316error 180: expected R_PAREN
322error 180: expected SEMI 317error 180: expected SEMI
323error 215: expected COMMA 318error 215: expected COMMA
324error 215: expected R_ANGLE 319error 215: expected R_ANGLE
diff --git a/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rs b/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rs
new file mode 100644
index 000000000..6e8b718aa
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.rs
@@ -0,0 +1,5 @@
1fn main() {
2 Some(for _ in [1].into_iter() {});
3 Some(loop { break; });
4 Some(while true {});
5}
diff --git a/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.txt b/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.txt
new file mode 100644
index 000000000..c011187ea
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/ok/0059_loops_in_parens.txt
@@ -0,0 +1,101 @@
1SOURCE_FILE@[0; 105)
2 FN_DEF@[0; 104)
3 FN_KW@[0; 2) "fn"
4 WHITESPACE@[2; 3) " "
5 NAME@[3; 7)
6 IDENT@[3; 7) "main"
7 PARAM_LIST@[7; 9)
8 L_PAREN@[7; 8) "("
9 R_PAREN@[8; 9) ")"
10 WHITESPACE@[9; 10) " "
11 BLOCK_EXPR@[10; 104)
12 BLOCK@[10; 104)
13 L_CURLY@[10; 11) "{"
14 WHITESPACE@[11; 16) "\n "
15 EXPR_STMT@[16; 50)
16 CALL_EXPR@[16; 49)
17 PATH_EXPR@[16; 20)
18 PATH@[16; 20)
19 PATH_SEGMENT@[16; 20)
20 NAME_REF@[16; 20)
21 IDENT@[16; 20) "Some"
22 ARG_LIST@[20; 49)
23 L_PAREN@[20; 21) "("
24 FOR_EXPR@[21; 48)
25 FOR_KW@[21; 24) "for"
26 WHITESPACE@[24; 25) " "
27 PLACEHOLDER_PAT@[25; 26)
28 UNDERSCORE@[25; 26) "_"
29 WHITESPACE@[26; 27) " "
30 IN_KW@[27; 29) "in"
31 WHITESPACE@[29; 30) " "
32 METHOD_CALL_EXPR@[30; 45)
33 ARRAY_EXPR@[30; 33)
34 L_BRACK@[30; 31) "["
35 LITERAL@[31; 32)
36 INT_NUMBER@[31; 32) "1"
37 R_BRACK@[32; 33) "]"
38 DOT@[33; 34) "."
39 NAME_REF@[34; 43)
40 IDENT@[34; 43) "into_iter"
41 ARG_LIST@[43; 45)
42 L_PAREN@[43; 44) "("
43 R_PAREN@[44; 45) ")"
44 WHITESPACE@[45; 46) " "
45 BLOCK_EXPR@[46; 48)
46 BLOCK@[46; 48)
47 L_CURLY@[46; 47) "{"
48 R_CURLY@[47; 48) "}"
49 R_PAREN@[48; 49) ")"
50 SEMI@[49; 50) ";"
51 WHITESPACE@[50; 55) "\n "
52 EXPR_STMT@[55; 77)
53 CALL_EXPR@[55; 76)
54 PATH_EXPR@[55; 59)
55 PATH@[55; 59)
56 PATH_SEGMENT@[55; 59)
57 NAME_REF@[55; 59)
58 IDENT@[55; 59) "Some"
59 ARG_LIST@[59; 76)
60 L_PAREN@[59; 60) "("
61 LOOP_EXPR@[60; 75)
62 LOOP_KW@[60; 64) "loop"
63 WHITESPACE@[64; 65) " "
64 BLOCK_EXPR@[65; 75)
65 BLOCK@[65; 75)
66 L_CURLY@[65; 66) "{"
67 WHITESPACE@[66; 67) " "
68 EXPR_STMT@[67; 73)
69 BREAK_EXPR@[67; 72)
70 BREAK_KW@[67; 72) "break"
71 SEMI@[72; 73) ";"
72 WHITESPACE@[73; 74) " "
73 R_CURLY@[74; 75) "}"
74 R_PAREN@[75; 76) ")"
75 SEMI@[76; 77) ";"
76 WHITESPACE@[77; 82) "\n "
77 EXPR_STMT@[82; 102)
78 CALL_EXPR@[82; 101)
79 PATH_EXPR@[82; 86)
80 PATH@[82; 86)
81 PATH_SEGMENT@[82; 86)
82 NAME_REF@[82; 86)
83 IDENT@[82; 86) "Some"
84 ARG_LIST@[86; 101)
85 L_PAREN@[86; 87) "("
86 WHILE_EXPR@[87; 100)
87 WHILE_KW@[87; 92) "while"
88 WHITESPACE@[92; 93) " "
89 CONDITION@[93; 97)
90 LITERAL@[93; 97)
91 TRUE_KW@[93; 97) "true"
92 WHITESPACE@[97; 98) " "
93 BLOCK_EXPR@[98; 100)
94 BLOCK@[98; 100)
95 L_CURLY@[98; 99) "{"
96 R_CURLY@[99; 100) "}"
97 R_PAREN@[100; 101) ")"
98 SEMI@[101; 102) ";"
99 WHITESPACE@[102; 103) "\n"
100 R_CURLY@[103; 104) "}"
101 WHITESPACE@[104; 105) "\n"