aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/subtree_source.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/subtree_source.rs')
-rw-r--r--crates/ra_mbe/src/subtree_source.rs47
1 files changed, 37 insertions, 10 deletions
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs
index 91e324db9..d7866452d 100644
--- a/crates/ra_mbe/src/subtree_source.rs
+++ b/crates/ra_mbe/src/subtree_source.rs
@@ -50,6 +50,26 @@ impl<'a> SubtreeTokenSource<'a> {
50 } 50 }
51 51
52 fn get(&self, pos: usize) -> Ref<Option<TtToken>> { 52 fn get(&self, pos: usize) -> Ref<Option<TtToken>> {
53 fn is_lifetime(c: Cursor) -> Option<(Cursor, SmolStr)> {
54 let tkn = c.token_tree();
55
56 if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = tkn {
57 if punct.char == '\'' {
58 let next = c.bump();
59 if let Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) = next.token_tree() {
60 let res_cursor = next.bump();
61 let text = SmolStr::new("'".to_string() + &ident.to_string());
62
63 return Some((res_cursor, text));
64 } else {
65 panic!("Next token must be ident : {:#?}", next.token_tree());
66 }
67 }
68 }
69
70 None
71 }
72
53 if pos < self.cached.borrow().len() { 73 if pos < self.cached.borrow().len() {
54 return Ref::map(self.cached.borrow(), |c| &c[pos]); 74 return Ref::map(self.cached.borrow(), |c| &c[pos]);
55 } 75 }
@@ -63,6 +83,12 @@ impl<'a> SubtreeTokenSource<'a> {
63 continue; 83 continue;
64 } 84 }
65 85
86 if let Some((curr, text)) = is_lifetime(cursor) {
87 cached.push(Some(TtToken { kind: LIFETIME, is_joint_to_next: false, text }));
88 self.cached_cursor.set(curr);
89 continue;
90 }
91
66 match cursor.token_tree() { 92 match cursor.token_tree() {
67 Some(tt::TokenTree::Leaf(leaf)) => { 93 Some(tt::TokenTree::Leaf(leaf)) => {
68 cached.push(Some(convert_leaf(&leaf))); 94 cached.push(Some(convert_leaf(&leaf)));
@@ -132,27 +158,28 @@ fn convert_literal(l: &tt::Literal) -> TtToken {
132 let kind = lex_single_syntax_kind(&l.text) 158 let kind = lex_single_syntax_kind(&l.text)
133 .map(|(kind, _error)| kind) 159 .map(|(kind, _error)| kind)
134 .filter(|kind| kind.is_literal()) 160 .filter(|kind| kind.is_literal())
135 .unwrap_or_else(|| match l.text.as_ref() { 161 .unwrap_or_else(|| panic!("Fail to convert given literal {:#?}", &l));
136 "true" => T![true],
137 "false" => T![false],
138 _ => panic!("Fail to convert given literal {:#?}", &l),
139 });
140 162
141 TtToken { kind, is_joint_to_next: false, text: l.text.clone() } 163 TtToken { kind, is_joint_to_next: false, text: l.text.clone() }
142} 164}
143 165
144fn convert_ident(ident: &tt::Ident) -> TtToken { 166fn convert_ident(ident: &tt::Ident) -> TtToken {
145 let kind = if ident.text.starts_with('\'') { 167 let kind = match ident.text.as_ref() {
146 LIFETIME 168 "true" => T![true],
147 } else { 169 "false" => T![false],
148 SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT) 170 i if i.starts_with('\'') => LIFETIME,
171 _ => SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT),
149 }; 172 };
150 173
151 TtToken { kind, is_joint_to_next: false, text: ident.text.clone() } 174 TtToken { kind, is_joint_to_next: false, text: ident.text.clone() }
152} 175}
153 176
154fn convert_punct(p: tt::Punct) -> TtToken { 177fn convert_punct(p: tt::Punct) -> TtToken {
155 let kind = SyntaxKind::from_char(p.char).unwrap(); 178 let kind = match SyntaxKind::from_char(p.char) {
179 None => panic!("{:#?} is not a valid punct", p),
180 Some(kind) => kind,
181 };
182
156 let text = { 183 let text = {
157 let mut buf = [0u8; 4]; 184 let mut buf = [0u8; 4];
158 let s: &str = p.char.encode_utf8(&mut buf); 185 let s: &str = p.char.encode_utf8(&mut buf);