aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-08-05 14:55:17 +0100
committerbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-08-05 14:55:17 +0100
commit12a7329cb3141e8b6e719cc08f1eea1bdb3fae3a (patch)
tree4048f6a71b825dd93d7c968bc44471143d69473b
parenta490f80a9c49380c5088b704047bb20b76c06e4d (diff)
parentf1cfd5ec3de3de39e5423e80a35c719463c4e5c0 (diff)
Merge #1648
1648: Optimize parsing a little r=lnicola a=lnicola This is the change from https://github.com/rust-analyzer/rust-analyzer/issues/1643#issuecomment-517979911. In the long run we should probably take a different approach, but until then this provides a decent speed-up (10.5s vs 11.5s according to `ra_cli analysis-stats`. EDIT: Does the profiling part make sense? I'm not sure if all parsing happens before the type inference begins or it's lazy. Co-authored-by: LaurenČ›iu Nicola <[email protected]> Co-authored-by: LaurenČ›iu Nicola <[email protected]>
-rw-r--r--crates/ra_cli/src/analysis_stats.rs6
-rw-r--r--crates/ra_parser/src/parser.rs54
2 files changed, 40 insertions, 20 deletions
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index 403aab352..7e7e6c073 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -52,6 +52,9 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
52 println!("Total modules found: {}", visited_modules.len()); 52 println!("Total modules found: {}", visited_modules.len());
53 println!("Total declarations: {}", num_decls); 53 println!("Total declarations: {}", num_decls);
54 println!("Total functions: {}", funcs.len()); 54 println!("Total functions: {}", funcs.len());
55 println!("Item Collection: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
56
57 let inference_time = Instant::now();
55 let bar = indicatif::ProgressBar::with_draw_target( 58 let bar = indicatif::ProgressBar::with_draw_target(
56 funcs.len() as u64, 59 funcs.len() as u64,
57 indicatif::ProgressDrawTarget::stderr_nohz(), 60 indicatif::ProgressDrawTarget::stderr_nohz(),
@@ -112,7 +115,8 @@ pub fn run(verbose: bool, memory_usage: bool, path: &Path, only: Option<&str>) -
112 num_exprs_partially_unknown, 115 num_exprs_partially_unknown,
113 (num_exprs_partially_unknown * 100 / num_exprs) 116 (num_exprs_partially_unknown * 100 / num_exprs)
114 ); 117 );
115 println!("Analysis: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage()); 118 println!("Inference: {:?}, {}", inference_time.elapsed(), ra_prof::memory_usage());
119 println!("Total: {:?}, {}", analysis_time.elapsed(), ra_prof::memory_usage());
116 120
117 if memory_usage { 121 if memory_usage {
118 drop(db); 122 drop(db);
diff --git a/crates/ra_parser/src/parser.rs b/crates/ra_parser/src/parser.rs
index 159ed50df..393586561 100644
--- a/crates/ra_parser/src/parser.rs
+++ b/crates/ra_parser/src/parser.rs
@@ -6,7 +6,7 @@ use crate::{
6 event::Event, 6 event::Event,
7 ParseError, 7 ParseError,
8 SyntaxKind::{self, EOF, ERROR, TOMBSTONE}, 8 SyntaxKind::{self, EOF, ERROR, TOMBSTONE},
9 TokenSet, TokenSource, T, 9 Token, TokenSet, TokenSource, T,
10}; 10};
11 11
12/// `Parser` struct provides the low-level API for 12/// `Parser` struct provides the low-level API for
@@ -87,8 +87,9 @@ impl<'t> Parser<'t> {
87 let mut i = 0; 87 let mut i = 0;
88 88
89 loop { 89 loop {
90 let mut kind = self.token_source.lookahead_nth(i).kind; 90 let token = self.token_source.lookahead_nth(i);
91 if let Some((composited, step)) = self.is_composite(kind, i) { 91 let mut kind = token.kind;
92 if let Some((composited, step)) = self.is_composite(token, i) {
92 kind = composited; 93 kind = composited;
93 i += step; 94 i += step;
94 } else { 95 } else {
@@ -250,32 +251,47 @@ impl<'t> Parser<'t> {
250 } 251 }
251 252
252 /// helper function for check if it is composite. 253 /// helper function for check if it is composite.
253 fn is_composite(&self, kind: SyntaxKind, n: usize) -> Option<(SyntaxKind, usize)> { 254 fn is_composite(&self, first: Token, n: usize) -> Option<(SyntaxKind, usize)> {
254 // We assume the dollars will not occuried between 255 // We assume the dollars will not occuried between
255 // mult-byte tokens 256 // mult-byte tokens
256 257
257 let first = self.token_source.lookahead_nth(n); 258 let jn1 = first.is_jointed_to_next;
259 if !jn1 && first.kind != T![-] {
260 return None;
261 }
262
258 let second = self.token_source.lookahead_nth(n + 1); 263 let second = self.token_source.lookahead_nth(n + 1);
264 if first.kind == T![-] && second.kind == T![>] {
265 return Some((T![->], 2));
266 }
267 if !jn1 {
268 return None;
269 }
270
271 match (first.kind, second.kind) {
272 (T![:], T![:]) => return Some((T![::], 2)),
273 (T![=], T![=]) => return Some((T![==], 2)),
274 (T![=], T![>]) => return Some((T![=>], 2)),
275 (T![!], T![=]) => return Some((T![!=], 2)),
276 _ => {}
277 }
278
279 if first.kind != T![.] || second.kind != T![.] {
280 return None;
281 }
282
259 let third = self.token_source.lookahead_nth(n + 2); 283 let third = self.token_source.lookahead_nth(n + 2);
260 284
261 let jn1 = first.is_jointed_to_next;
262 let la2 = second.kind;
263 let jn2 = second.is_jointed_to_next; 285 let jn2 = second.is_jointed_to_next;
264 let la3 = third.kind; 286 let la3 = third.kind;
265 287
266 match kind { 288 if jn2 && la3 == T![.] {
267 T![.] if jn1 && la2 == T![.] && jn2 && la3 == T![.] => Some((T![...], 3)), 289 return Some((T![...], 3));
268 T![.] if jn1 && la2 == T![.] && la3 == T![=] => Some((T![..=], 3)), 290 }
269 T![.] if jn1 && la2 == T![.] => Some((T![..], 2)), 291 if la3 == T![=] {
270 292 return Some((T![..=], 3));
271 T![:] if jn1 && la2 == T![:] => Some((T![::], 2)),
272 T![=] if jn1 && la2 == T![=] => Some((T![==], 2)),
273 T![=] if jn1 && la2 == T![>] => Some((T![=>], 2)),
274
275 T![!] if jn1 && la2 == T![=] => Some((T![!=], 2)),
276 T![-] if la2 == T![>] => Some((T![->], 2)),
277 _ => None,
278 } 293 }
294 return Some((T![..], 2));
279 } 295 }
280 296
281 fn eat_dollars(&mut self) { 297 fn eat_dollars(&mut self) {