aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_syntax/src/ast.rs4
-rw-r--r--crates/ra_syntax/src/grammar.ron5
-rw-r--r--crates/ra_syntax/src/grammar.rs4
-rw-r--r--crates/ra_syntax/src/grammar/expressions.rs8
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs1
-rw-r--r--crates/ra_syntax/src/grammar/items.rs10
-rw-r--r--crates/ra_syntax/src/grammar/items/nominal.rs4
-rw-r--r--crates/ra_syntax/src/grammar/items/traits.rs2
-rw-r--r--crates/ra_syntax/src/grammar/params.rs6
-rw-r--r--crates/ra_syntax/src/grammar/paths.rs6
-rw-r--r--crates/ra_syntax/src/grammar/patterns.rs6
-rw-r--r--crates/ra_syntax/src/grammar/type_args.rs2
-rw-r--r--crates/ra_syntax/src/grammar/type_params.rs4
-rw-r--r--crates/ra_syntax/src/lexer.rs21
-rw-r--r--crates/ra_syntax/src/lexer/strings.rs3
-rw-r--r--crates/ra_syntax/src/parser_api.rs8
-rw-r--r--crates/ra_syntax/src/reparsing.rs4
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs10
-rw-r--r--crates/ra_syntax/src/syntax_kinds/generated.rs.tera9
-rw-r--r--crates/ra_syntax/src/yellow.rs2
-rw-r--r--crates/ra_syntax/tests/data/lexer/0016_raw_ident.rs1
-rw-r--r--crates/ra_syntax/tests/data/lexer/0016_raw_ident.txt2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.rs2
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.txt15
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.rs3
-rw-r--r--crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.txt22
26 files changed, 124 insertions, 40 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index bcbd4c60c..4d8412d46 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -142,7 +142,7 @@ impl Attr {
142 pub fn as_atom(&self) -> Option<SmolStr> { 142 pub fn as_atom(&self) -> Option<SmolStr> {
143 let tt = self.value()?; 143 let tt = self.value()?;
144 let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?; 144 let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?;
145 if attr.kind() == IDENT { 145 if attr.kind().is_ident() {
146 Some(attr.leaf_text().unwrap().clone()) 146 Some(attr.leaf_text().unwrap().clone())
147 } else { 147 } else {
148 None 148 None
@@ -153,7 +153,7 @@ impl Attr {
153 let tt = self.value()?; 153 let tt = self.value()?;
154 let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?; 154 let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?;
155 let args = TokenTree::cast(args)?; 155 let args = TokenTree::cast(args)?;
156 if attr.kind() == IDENT { 156 if attr.kind().is_ident() {
157 Some((attr.leaf_text().unwrap().clone(), args)) 157 Some((attr.leaf_text().unwrap().clone(), args))
158 } else { 158 } else {
159 None 159 None
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 0385183fd..64beb8252 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -102,6 +102,7 @@ Grammar(
102 tokens: [ 102 tokens: [
103 "ERROR", 103 "ERROR",
104 "IDENT", 104 "IDENT",
105 "RAW_IDENT",
105 "UNDERSCORE", 106 "UNDERSCORE",
106 "WHITESPACE", 107 "WHITESPACE",
107 "INT_NUMBER", 108 "INT_NUMBER",
@@ -116,6 +117,10 @@ Grammar(
116 "COMMENT", 117 "COMMENT",
117 "SHEBANG", 118 "SHEBANG",
118 ], 119 ],
120 ident_tokens: [
121 "IDENT",
122 "RAW_IDENT",
123 ],
119 nodes: [ 124 nodes: [
120 "SOURCE_FILE", 125 "SOURCE_FILE",
121 126
diff --git a/crates/ra_syntax/src/grammar.rs b/crates/ra_syntax/src/grammar.rs
index 060c0ccdf..531d0458f 100644
--- a/crates/ra_syntax/src/grammar.rs
+++ b/crates/ra_syntax/src/grammar.rs
@@ -140,7 +140,7 @@ fn opt_fn_ret_type(p: &mut Parser) -> bool {
140} 140}
141 141
142fn name_r(p: &mut Parser, recovery: TokenSet) { 142fn name_r(p: &mut Parser, recovery: TokenSet) {
143 if p.at(IDENT) { 143 if p.current().is_ident() {
144 let m = p.start(); 144 let m = p.start();
145 p.bump(); 145 p.bump();
146 m.complete(p, NAME); 146 m.complete(p, NAME);
@@ -154,7 +154,7 @@ fn name(p: &mut Parser) {
154} 154}
155 155
156fn name_ref(p: &mut Parser) { 156fn name_ref(p: &mut Parser) {
157 if p.at(IDENT) { 157 if p.current().is_ident() {
158 let m = p.start(); 158 let m = p.start();
159 p.bump(); 159 p.bump();
160 m.complete(p, NAME_REF); 160 m.complete(p, NAME_REF);
diff --git a/crates/ra_syntax/src/grammar/expressions.rs b/crates/ra_syntax/src/grammar/expressions.rs
index 2236555e0..107b7cda4 100644
--- a/crates/ra_syntax/src/grammar/expressions.rs
+++ b/crates/ra_syntax/src/grammar/expressions.rs
@@ -281,7 +281,7 @@ fn postfix_expr(
281 // } 281 // }
282 L_PAREN if allow_calls => call_expr(p, lhs), 282 L_PAREN if allow_calls => call_expr(p, lhs),
283 L_BRACK if allow_calls => index_expr(p, lhs), 283 L_BRACK if allow_calls => index_expr(p, lhs),
284 DOT if p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON) => { 284 DOT if p.nth(1).is_ident() && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON) => {
285 method_call_expr(p, lhs) 285 method_call_expr(p, lhs)
286 } 286 }
287 DOT => field_expr(p, lhs), 287 DOT => field_expr(p, lhs),
@@ -332,7 +332,7 @@ fn index_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
332// y.bar::<T>(1, 2,); 332// y.bar::<T>(1, 2,);
333// } 333// }
334fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker { 334fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
335 assert!(p.at(DOT) && p.nth(1) == IDENT && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON)); 335 assert!(p.at(DOT) && p.nth(1).is_ident() && (p.nth(2) == L_PAREN || p.nth(2) == COLONCOLON));
336 let m = lhs.precede(p); 336 let m = lhs.precede(p);
337 p.bump(); 337 p.bump();
338 name_ref(p); 338 name_ref(p);
@@ -352,7 +352,7 @@ fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
352 assert!(p.at(DOT)); 352 assert!(p.at(DOT));
353 let m = lhs.precede(p); 353 let m = lhs.precede(p);
354 p.bump(); 354 p.bump();
355 if p.at(IDENT) { 355 if p.current().is_ident() {
356 name_ref(p) 356 name_ref(p)
357 } else if p.at(INT_NUMBER) { 357 } else if p.at(INT_NUMBER) {
358 p.bump() 358 p.bump()
@@ -443,7 +443,7 @@ pub(crate) fn named_field_list(p: &mut Parser) {
443 p.bump(); 443 p.bump();
444 while !p.at(EOF) && !p.at(R_CURLY) { 444 while !p.at(EOF) && !p.at(R_CURLY) {
445 match p.current() { 445 match p.current() {
446 IDENT => { 446 IDENT | RAW_IDENT => {
447 let m = p.start(); 447 let m = p.start();
448 name_ref(p); 448 name_ref(p);
449 if p.eat(COLON) { 449 if p.eat(COLON) {
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs
index 167a76551..3fbe22856 100644
--- a/crates/ra_syntax/src/grammar/expressions/atom.rs
+++ b/crates/ra_syntax/src/grammar/expressions/atom.rs
@@ -48,6 +48,7 @@ pub(super) const ATOM_EXPR_FIRST: TokenSet = LITERAL_FIRST.union(token_set![
48 UNSAFE_KW, 48 UNSAFE_KW,
49 RETURN_KW, 49 RETURN_KW,
50 IDENT, 50 IDENT,
51 RAW_IDENT,
51 SELF_KW, 52 SELF_KW,
52 SUPER_KW, 53 SUPER_KW,
53 CRATE_KW, 54 CRATE_KW,
diff --git a/crates/ra_syntax/src/grammar/items.rs b/crates/ra_syntax/src/grammar/items.rs
index 265e84570..c49798444 100644
--- a/crates/ra_syntax/src/grammar/items.rs
+++ b/crates/ra_syntax/src/grammar/items.rs
@@ -99,11 +99,11 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
99 has_mods = true; 99 has_mods = true;
100 abi(p); 100 abi(p);
101 } 101 }
102 if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW { 102 if p.current().is_ident() && p.at_contextual_kw("auto") && p.nth(1) == TRAIT_KW {
103 p.bump_remap(AUTO_KW); 103 p.bump_remap(AUTO_KW);
104 has_mods = true; 104 has_mods = true;
105 } 105 }
106 if p.at(IDENT) && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW { 106 if p.current().is_ident() && p.at_contextual_kw("default") && p.nth(1) == IMPL_KW {
107 p.bump_remap(DEFAULT_KW); 107 p.bump_remap(DEFAULT_KW);
108 has_mods = true; 108 has_mods = true;
109 } 109 }
@@ -202,7 +202,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
202 } 202 }
203 STRUCT_DEF 203 STRUCT_DEF
204 } 204 }
205 IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => { 205 IDENT | RAW_IDENT if p.at_contextual_kw("union") && p.nth(1).is_ident() => {
206 // test union_items 206 // test union_items
207 // union Foo {} 207 // union Foo {}
208 // union Foo { 208 // union Foo {
@@ -220,7 +220,7 @@ fn items_without_modifiers(p: &mut Parser) -> Option<SyntaxKind> {
220 use_item::use_item(p); 220 use_item::use_item(p);
221 USE_ITEM 221 USE_ITEM
222 } 222 }
223 CONST_KW if (la == IDENT || la == MUT_KW) => { 223 CONST_KW if (la.is_ident() || la == MUT_KW) => {
224 consts::const_def(p); 224 consts::const_def(p);
225 CONST_DEF 225 CONST_DEF
226 } 226 }
@@ -351,7 +351,7 @@ fn macro_call(p: &mut Parser) -> BlockLike {
351 351
352pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike { 352pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
353 p.expect(EXCL); 353 p.expect(EXCL);
354 p.eat(IDENT); 354 p.eat_one(&[IDENT, RAW_IDENT]);
355 match p.current() { 355 match p.current() {
356 L_CURLY => { 356 L_CURLY => {
357 token_tree(p); 357 token_tree(p);
diff --git a/crates/ra_syntax/src/grammar/items/nominal.rs b/crates/ra_syntax/src/grammar/items/nominal.rs
index 0784fb7b1..897306883 100644
--- a/crates/ra_syntax/src/grammar/items/nominal.rs
+++ b/crates/ra_syntax/src/grammar/items/nominal.rs
@@ -70,7 +70,7 @@ pub(crate) fn enum_variant_list(p: &mut Parser) {
70 } 70 }
71 let var = p.start(); 71 let var = p.start();
72 attributes::outer_attributes(p); 72 attributes::outer_attributes(p);
73 if p.at(IDENT) { 73 if p.current().is_ident() {
74 name(p); 74 name(p);
75 match p.current() { 75 match p.current() {
76 L_CURLY => named_field_def_list(p), 76 L_CURLY => named_field_def_list(p),
@@ -120,7 +120,7 @@ pub(crate) fn named_field_def_list(p: &mut Parser) {
120 // } 120 // }
121 attributes::outer_attributes(p); 121 attributes::outer_attributes(p);
122 opt_visibility(p); 122 opt_visibility(p);
123 if p.at(IDENT) { 123 if p.current().is_ident() {
124 name(p); 124 name(p);
125 p.expect(COLON); 125 p.expect(COLON);
126 types::type_(p); 126 types::type_(p);
diff --git a/crates/ra_syntax/src/grammar/items/traits.rs b/crates/ra_syntax/src/grammar/items/traits.rs
index 0a0621753..a78bbba2b 100644
--- a/crates/ra_syntax/src/grammar/items/traits.rs
+++ b/crates/ra_syntax/src/grammar/items/traits.rs
@@ -112,7 +112,7 @@ fn choose_type_params_over_qpath(p: &Parser) -> bool {
112 if p.nth(1) == POUND || p.nth(1) == R_ANGLE { 112 if p.nth(1) == POUND || p.nth(1) == R_ANGLE {
113 return true; 113 return true;
114 } 114 }
115 (p.nth(1) == LIFETIME || p.nth(1) == IDENT) 115 (p.nth(1) == LIFETIME || p.nth(1).is_ident())
116 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ) 116 && (p.nth(2) == R_ANGLE || p.nth(2) == COMMA || p.nth(2) == COLON || p.nth(2) == EQ)
117} 117}
118 118
diff --git a/crates/ra_syntax/src/grammar/params.rs b/crates/ra_syntax/src/grammar/params.rs
index 13158429a..ada07c17e 100644
--- a/crates/ra_syntax/src/grammar/params.rs
+++ b/crates/ra_syntax/src/grammar/params.rs
@@ -84,9 +84,9 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
84 // trait Foo { 84 // trait Foo {
85 // fn bar(_: u64); 85 // fn bar(_: u64);
86 // } 86 // }
87 if (la0 == IDENT || la0 == UNDERSCORE) && la1 == COLON 87 if (la0.is_ident() || la0 == UNDERSCORE) && la1 == COLON
88 || la0 == AMP && la1 == IDENT && la2 == COLON 88 || la0 == AMP && la1.is_ident() && la2 == COLON
89 || la0 == AMP && la1 == MUT_KW && la2 == IDENT && la3 == COLON 89 || la0 == AMP && la1 == MUT_KW && la2.is_ident() && la3 == COLON
90 { 90 {
91 patterns::pattern(p); 91 patterns::pattern(p);
92 types::ascription(p); 92 types::ascription(p);
diff --git a/crates/ra_syntax/src/grammar/paths.rs b/crates/ra_syntax/src/grammar/paths.rs
index 33a11886c..0e1c1d334 100644
--- a/crates/ra_syntax/src/grammar/paths.rs
+++ b/crates/ra_syntax/src/grammar/paths.rs
@@ -1,11 +1,11 @@
1use super::*; 1use super::*;
2 2
3pub(super) const PATH_FIRST: TokenSet = 3pub(super) const PATH_FIRST: TokenSet =
4 token_set![IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, L_ANGLE]; 4 token_set![IDENT, RAW_IDENT, SELF_KW, SUPER_KW, CRATE_KW, COLONCOLON, L_ANGLE];
5 5
6pub(super) fn is_path_start(p: &Parser) -> bool { 6pub(super) fn is_path_start(p: &Parser) -> bool {
7 match p.current() { 7 match p.current() {
8 IDENT | SELF_KW | SUPER_KW | CRATE_KW | COLONCOLON => true, 8 IDENT | RAW_IDENT | SELF_KW | SUPER_KW | CRATE_KW | COLONCOLON => true,
9 _ => false, 9 _ => false,
10 } 10 }
11} 11}
@@ -70,7 +70,7 @@ fn path_segment(p: &mut Parser, mode: Mode, first: bool) {
70 p.eat(COLONCOLON); 70 p.eat(COLONCOLON);
71 } 71 }
72 match p.current() { 72 match p.current() {
73 IDENT => { 73 IDENT | RAW_IDENT => {
74 name_ref(p); 74 name_ref(p);
75 opt_path_type_args(p, mode); 75 opt_path_type_args(p, mode);
76 } 76 }
diff --git a/crates/ra_syntax/src/grammar/patterns.rs b/crates/ra_syntax/src/grammar/patterns.rs
index 1ac5efdf6..925eabe1b 100644
--- a/crates/ra_syntax/src/grammar/patterns.rs
+++ b/crates/ra_syntax/src/grammar/patterns.rs
@@ -37,7 +37,7 @@ fn atom_pat(p: &mut Parser, recovery_set: TokenSet) -> Option<CompletedMarker> {
37 let la1 = p.nth(1); 37 let la1 = p.nth(1);
38 if la0 == REF_KW 38 if la0 == REF_KW
39 || la0 == MUT_KW 39 || la0 == MUT_KW
40 || (la0 == IDENT && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY)) 40 || (la0.is_ident() && !(la1 == COLONCOLON || la1 == L_PAREN || la1 == L_CURLY))
41 { 41 {
42 return Some(bind_pat(p, true)); 42 return Some(bind_pat(p, true));
43 } 43 }
@@ -128,7 +128,7 @@ fn field_pat_list(p: &mut Parser) {
128 while !p.at(EOF) && !p.at(R_CURLY) { 128 while !p.at(EOF) && !p.at(R_CURLY) {
129 match p.current() { 129 match p.current() {
130 DOTDOT => p.bump(), 130 DOTDOT => p.bump(),
131 IDENT if p.nth(1) == COLON => field_pat(p), 131 IDENT | RAW_IDENT if p.nth(1) == COLON => field_pat(p),
132 L_CURLY => error_block(p, "expected ident"), 132 L_CURLY => error_block(p, "expected ident"),
133 _ => { 133 _ => {
134 bind_pat(p, false); 134 bind_pat(p, false);
@@ -143,7 +143,7 @@ fn field_pat_list(p: &mut Parser) {
143} 143}
144 144
145fn field_pat(p: &mut Parser) { 145fn field_pat(p: &mut Parser) {
146 assert!(p.at(IDENT)); 146 assert!(p.current().is_ident());
147 assert!(p.nth(1) == COLON); 147 assert!(p.nth(1) == COLON);
148 148
149 let m = p.start(); 149 let m = p.start();
diff --git a/crates/ra_syntax/src/grammar/type_args.rs b/crates/ra_syntax/src/grammar/type_args.rs
index f889419c5..469595d71 100644
--- a/crates/ra_syntax/src/grammar/type_args.rs
+++ b/crates/ra_syntax/src/grammar/type_args.rs
@@ -34,7 +34,7 @@ fn type_arg(p: &mut Parser) {
34 p.bump(); 34 p.bump();
35 m.complete(p, LIFETIME_ARG); 35 m.complete(p, LIFETIME_ARG);
36 } 36 }
37 IDENT if p.nth(1) == EQ => { 37 IDENT | RAW_IDENT if p.nth(1) == EQ => {
38 name_ref(p); 38 name_ref(p);
39 p.bump(); 39 p.bump();
40 types::type_(p); 40 types::type_(p);
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs
index 1ec813b3e..3cebd0675 100644
--- a/crates/ra_syntax/src/grammar/type_params.rs
+++ b/crates/ra_syntax/src/grammar/type_params.rs
@@ -15,7 +15,7 @@ fn type_param_list(p: &mut Parser) {
15 while !p.at(EOF) && !p.at(R_ANGLE) { 15 while !p.at(EOF) && !p.at(R_ANGLE) {
16 match p.current() { 16 match p.current() {
17 LIFETIME => lifetime_param(p), 17 LIFETIME => lifetime_param(p),
18 IDENT => type_param(p), 18 IDENT | RAW_IDENT => type_param(p),
19 _ => p.err_and_bump("expected type parameter"), 19 _ => p.err_and_bump("expected type parameter"),
20 } 20 }
21 if !p.at(R_ANGLE) && !p.expect(COMMA) { 21 if !p.at(R_ANGLE) && !p.expect(COMMA) {
@@ -37,7 +37,7 @@ fn lifetime_param(p: &mut Parser) {
37} 37}
38 38
39fn type_param(p: &mut Parser) { 39fn type_param(p: &mut Parser) {
40 assert!(p.at(IDENT)); 40 assert!(p.current().is_ident());
41 let m = p.start(); 41 let m = p.start();
42 name(p); 42 name(p);
43 if p.at(COLON) { 43 if p.at(COLON) {
diff --git a/crates/ra_syntax/src/lexer.rs b/crates/ra_syntax/src/lexer.rs
index c6acd095e..fab184a2d 100644
--- a/crates/ra_syntax/src/lexer.rs
+++ b/crates/ra_syntax/src/lexer.rs
@@ -190,19 +190,24 @@ fn next_token_inner(c: char, ptr: &mut Ptr) -> SyntaxKind {
190} 190}
191 191
192fn scan_ident(c: char, ptr: &mut Ptr) -> SyntaxKind { 192fn scan_ident(c: char, ptr: &mut Ptr) -> SyntaxKind {
193 let is_single_letter = match ptr.current() { 193 let is_raw = match (c, ptr.current()) {
194 None => true, 194 ('r', Some('#')) => {
195 Some(c) if !is_ident_continue(c) => true, 195 ptr.bump();
196 true
197 }
198 ('_', Some(c)) if !is_ident_continue(c) => return UNDERSCORE,
196 _ => false, 199 _ => false,
197 }; 200 };
198 if is_single_letter { 201
199 return if c == '_' { UNDERSCORE } else { IDENT };
200 }
201 ptr.bump_while(is_ident_continue); 202 ptr.bump_while(is_ident_continue);
202 if let Some(kind) = SyntaxKind::from_keyword(ptr.current_token_text()) { 203
204 if is_raw {
205 RAW_IDENT
206 } else if let Some(kind) = SyntaxKind::from_keyword(ptr.current_token_text()) {
203 return kind; 207 return kind;
208 } else {
209 IDENT
204 } 210 }
205 IDENT
206} 211}
207 212
208fn scan_literal_suffix(ptr: &mut Ptr) { 213fn scan_literal_suffix(ptr: &mut Ptr) {
diff --git a/crates/ra_syntax/src/lexer/strings.rs b/crates/ra_syntax/src/lexer/strings.rs
index 0865b7f3b..5c1cf3e9c 100644
--- a/crates/ra_syntax/src/lexer/strings.rs
+++ b/crates/ra_syntax/src/lexer/strings.rs
@@ -5,7 +5,8 @@ use crate::lexer::ptr::Ptr;
5pub(crate) fn is_string_literal_start(c: char, c1: Option<char>, c2: Option<char>) -> bool { 5pub(crate) fn is_string_literal_start(c: char, c1: Option<char>, c2: Option<char>) -> bool {
6 match (c, c1, c2) { 6 match (c, c1, c2) {
7 ('r', Some('"'), _) 7 ('r', Some('"'), _)
8 | ('r', Some('#'), _) 8 | ('r', Some('#'), Some('"'))
9 | ('r', Some('#'), Some('#'))
9 | ('b', Some('"'), _) 10 | ('b', Some('"'), _)
10 | ('b', Some('\''), _) 11 | ('b', Some('\''), _)
11 | ('b', Some('r'), Some('"')) 12 | ('b', Some('r'), Some('"'))
diff --git a/crates/ra_syntax/src/parser_api.rs b/crates/ra_syntax/src/parser_api.rs
index 3148371c5..d795cbaf1 100644
--- a/crates/ra_syntax/src/parser_api.rs
+++ b/crates/ra_syntax/src/parser_api.rs
@@ -100,6 +100,14 @@ impl<'t> Parser<'t> {
100 true 100 true
101 } 101 }
102 102
103 /// Consume the next token matching one of the `kinds`
104 pub(crate) fn eat_one<'k, K>(&mut self, kinds: K) -> bool
105 where
106 K: IntoIterator<Item = &'k SyntaxKind> + 'k,
107 {
108 kinds.into_iter().map(|k| self.eat(*k)).any(|eaten| eaten)
109 }
110
103 /// Consume the next token if it is `kind` or emit an error 111 /// Consume the next token if it is `kind` or emit an error
104 /// otherwise. 112 /// otherwise.
105 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool { 113 pub(crate) fn expect(&mut self, kind: SyntaxKind) -> bool {
diff --git a/crates/ra_syntax/src/reparsing.rs b/crates/ra_syntax/src/reparsing.rs
index 2f1de6b02..b38985bc8 100644
--- a/crates/ra_syntax/src/reparsing.rs
+++ b/crates/ra_syntax/src/reparsing.rs
@@ -25,7 +25,7 @@ fn reparse_leaf<'node>(
25) -> Option<(&'node SyntaxNode, GreenNode, Vec<SyntaxError>)> { 25) -> Option<(&'node SyntaxNode, GreenNode, Vec<SyntaxError>)> {
26 let node = algo::find_covering_node(node, edit.delete); 26 let node = algo::find_covering_node(node, edit.delete);
27 match node.kind() { 27 match node.kind() {
28 WHITESPACE | COMMENT | IDENT | STRING | RAW_STRING => { 28 WHITESPACE | COMMENT | IDENT | RAW_IDENT | STRING | RAW_STRING => {
29 let text = get_text_after_edit(node, &edit); 29 let text = get_text_after_edit(node, &edit);
30 let tokens = tokenize(&text); 30 let tokens = tokenize(&text);
31 let token = match tokens[..] { 31 let token = match tokens[..] {
@@ -33,7 +33,7 @@ fn reparse_leaf<'node>(
33 _ => return None, 33 _ => return None,
34 }; 34 };
35 35
36 if token.kind == IDENT && is_contextual_kw(&text) { 36 if token.kind.is_ident() && is_contextual_kw(&text) {
37 return None; 37 return None;
38 } 38 }
39 39
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs b/crates/ra_syntax/src/syntax_kinds/generated.rs
index 06faf7557..aa1ab3326 100644
--- a/crates/ra_syntax/src/syntax_kinds/generated.rs
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs
@@ -105,6 +105,7 @@ pub enum SyntaxKind {
105 UNION_KW, 105 UNION_KW,
106 ERROR, 106 ERROR,
107 IDENT, 107 IDENT,
108 RAW_IDENT,
108 UNDERSCORE, 109 UNDERSCORE,
109 WHITESPACE, 110 WHITESPACE,
110 INT_NUMBER, 111 INT_NUMBER,
@@ -368,6 +369,7 @@ impl SyntaxKind {
368 UNION_KW => &SyntaxInfo { name: "UNION_KW" }, 369 UNION_KW => &SyntaxInfo { name: "UNION_KW" },
369 ERROR => &SyntaxInfo { name: "ERROR" }, 370 ERROR => &SyntaxInfo { name: "ERROR" },
370 IDENT => &SyntaxInfo { name: "IDENT" }, 371 IDENT => &SyntaxInfo { name: "IDENT" },
372 RAW_IDENT => &SyntaxInfo { name: "RAW_IDENT" },
371 UNDERSCORE => &SyntaxInfo { name: "UNDERSCORE" }, 373 UNDERSCORE => &SyntaxInfo { name: "UNDERSCORE" },
372 WHITESPACE => &SyntaxInfo { name: "WHITESPACE" }, 374 WHITESPACE => &SyntaxInfo { name: "WHITESPACE" },
373 INT_NUMBER => &SyntaxInfo { name: "INT_NUMBER" }, 375 INT_NUMBER => &SyntaxInfo { name: "INT_NUMBER" },
@@ -563,4 +565,12 @@ impl SyntaxKind {
563 }; 565 };
564 Some(tok) 566 Some(tok)
565 } 567 }
568
569 pub(crate) fn is_ident(&self) -> bool {
570 match self {
571 | IDENT
572 | RAW_IDENT => true,
573 _ => false,
574 }
575 }
566} 576}
diff --git a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
index 21f9444b1..83787f820 100644
--- a/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
+++ b/crates/ra_syntax/src/syntax_kinds/generated.rs.tera
@@ -74,4 +74,13 @@ impl SyntaxKind {
74 }; 74 };
75 Some(tok) 75 Some(tok)
76 } 76 }
77
78 pub(crate) fn is_ident(&self) -> bool {
79 match self {
80{%- for kind in ident_tokens %}
81 | {{kind}}
82{%- endfor %} => true,
83 _ => false,
84 }
85 }
77} 86}
diff --git a/crates/ra_syntax/src/yellow.rs b/crates/ra_syntax/src/yellow.rs
index a7bfb80e2..48f01128b 100644
--- a/crates/ra_syntax/src/yellow.rs
+++ b/crates/ra_syntax/src/yellow.rs
@@ -207,7 +207,7 @@ impl<'a> Iterator for SyntaxNodeChildren<'a> {
207fn has_short_text(kind: SyntaxKind) -> bool { 207fn has_short_text(kind: SyntaxKind) -> bool {
208 use crate::SyntaxKind::*; 208 use crate::SyntaxKind::*;
209 match kind { 209 match kind {
210 IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true, 210 IDENT | RAW_IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
211 _ => false, 211 _ => false,
212 } 212 }
213} 213}
diff --git a/crates/ra_syntax/tests/data/lexer/0016_raw_ident.rs b/crates/ra_syntax/tests/data/lexer/0016_raw_ident.rs
new file mode 100644
index 000000000..b40a1b6a2
--- /dev/null
+++ b/crates/ra_syntax/tests/data/lexer/0016_raw_ident.rs
@@ -0,0 +1 @@
r#raw_ident
diff --git a/crates/ra_syntax/tests/data/lexer/0016_raw_ident.txt b/crates/ra_syntax/tests/data/lexer/0016_raw_ident.txt
new file mode 100644
index 000000000..28b9b208a
--- /dev/null
+++ b/crates/ra_syntax/tests/data/lexer/0016_raw_ident.txt
@@ -0,0 +1,2 @@
1RAW_IDENT 11 "r#raw_ident"
2WHITESPACE 1 "\n"
diff --git a/crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.rs b/crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.rs
new file mode 100644
index 000000000..8380d1e79
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.rs
@@ -0,0 +1,2 @@
1fn r#foo() {
2}
diff --git a/crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.txt b/crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.txt
new file mode 100644
index 000000000..865a680f2
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0039_raw_fn_item.txt
@@ -0,0 +1,15 @@
1SOURCE_FILE@[0; 15)
2 FN_DEF@[0; 14)
3 FN_KW@[0; 2)
4 WHITESPACE@[2; 3)
5 NAME@[3; 8)
6 RAW_IDENT@[3; 8) "r#foo"
7 PARAM_LIST@[8; 10)
8 L_PAREN@[8; 9)
9 R_PAREN@[9; 10)
10 WHITESPACE@[10; 11)
11 BLOCK@[11; 14)
12 L_CURLY@[11; 12)
13 WHITESPACE@[12; 13)
14 R_CURLY@[13; 14)
15 WHITESPACE@[14; 15)
diff --git a/crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.rs b/crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.rs
new file mode 100644
index 000000000..098a60a72
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.rs
@@ -0,0 +1,3 @@
1struct S {
2 r#foo: u32
3} \ No newline at end of file
diff --git a/crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.txt b/crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.txt
new file mode 100644
index 000000000..4e244cbc5
--- /dev/null
+++ b/crates/ra_syntax/tests/data/parser/ok/0040_raw_struct_item_field.txt
@@ -0,0 +1,22 @@
1SOURCE_FILE@[0; 27)
2 STRUCT_DEF@[0; 27)
3 STRUCT_KW@[0; 6)
4 WHITESPACE@[6; 7)
5 NAME@[7; 8)
6 IDENT@[7; 8) "S"
7 WHITESPACE@[8; 9)
8 NAMED_FIELD_DEF_LIST@[9; 27)
9 L_CURLY@[9; 10)
10 WHITESPACE@[10; 15)
11 NAMED_FIELD_DEF@[15; 25)
12 NAME@[15; 20)
13 RAW_IDENT@[15; 20) "r#foo"
14 COLON@[20; 21)
15 WHITESPACE@[21; 22)
16 PATH_TYPE@[22; 25)
17 PATH@[22; 25)
18 PATH_SEGMENT@[22; 25)
19 NAME_REF@[22; 25)
20 IDENT@[22; 25) "u32"
21 WHITESPACE@[25; 26)
22 R_CURLY@[26; 27)