diff options
author | Aleksey Kladov <[email protected]> | 2020-11-06 18:01:25 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2020-11-06 18:09:01 +0000 |
commit | eb460333907a44c37bf7287b31c653877c3358c2 (patch) | |
tree | 1f048935ea6b51cc1e5f01d0613552264b31f02d /crates/syntax/src/ast | |
parent | 735aaa7b39b4d3d789ad75c167bbf322a65ca257 (diff) |
More orthogonal API
Diffstat (limited to 'crates/syntax/src/ast')
-rw-r--r-- | crates/syntax/src/ast/token_ext.rs | 63 |
1 files changed, 30 insertions, 33 deletions
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index 5623799b4..8d3fad5a6 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs | |||
@@ -166,6 +166,7 @@ impl HasStringValue for ast::String { | |||
166 | } | 166 | } |
167 | } | 167 | } |
168 | 168 | ||
169 | // FIXME: merge `ast::RawString` and `ast::String`. | ||
169 | impl HasStringValue for ast::RawString { | 170 | impl HasStringValue for ast::RawString { |
170 | fn value(&self) -> Option<Cow<'_, str>> { | 171 | fn value(&self) -> Option<Cow<'_, str>> { |
171 | let text = self.text().as_str(); | 172 | let text = self.text().as_str(); |
@@ -544,29 +545,46 @@ impl ast::IntNumber { | |||
544 | "i8", "i16", "i32", "i64", "i128", "isize", | 545 | "i8", "i16", "i32", "i64", "i128", "isize", |
545 | ]; | 546 | ]; |
546 | 547 | ||
547 | // FIXME: should probably introduce string token type? | 548 | pub fn radix(&self) -> Radix { |
548 | // https://github.com/rust-analyzer/rust-analyzer/issues/6308 | 549 | match self.text().get(..2).unwrap_or_default() { |
549 | pub fn value(&self) -> Option<(Radix, u128)> { | 550 | "0b" => Radix::Binary, |
551 | "0o" => Radix::Octal, | ||
552 | "0x" => Radix::Hexadecimal, | ||
553 | _ => Radix::Decimal, | ||
554 | } | ||
555 | } | ||
556 | |||
557 | pub fn value(&self) -> Option<u128> { | ||
550 | let token = self.syntax(); | 558 | let token = self.syntax(); |
551 | 559 | ||
552 | let mut text = token.text().as_str(); | 560 | let mut text = token.text().as_str(); |
553 | for suffix in ast::IntNumber::SUFFIXES { | 561 | if let Some(suffix) = self.suffix() { |
554 | if let Some(without_suffix) = text.strip_suffix(suffix) { | 562 | text = &text[..text.len() - suffix.len()] |
555 | text = without_suffix; | ||
556 | break; | ||
557 | } | ||
558 | } | 563 | } |
559 | 564 | ||
565 | let radix = self.radix(); | ||
566 | text = &text[radix.prefix_len()..]; | ||
567 | |||
560 | let buf; | 568 | let buf; |
561 | if text.contains("_") { | 569 | if text.contains("_") { |
562 | buf = text.replace('_', ""); | 570 | buf = text.replace('_', ""); |
563 | text = buf.as_str(); | 571 | text = buf.as_str(); |
564 | }; | 572 | }; |
565 | 573 | ||
566 | let radix = Radix::identify(text)?; | 574 | let value = u128::from_str_radix(text, radix as u32).ok()?; |
567 | let digits = &text[radix.prefix_len()..]; | 575 | Some(value) |
568 | let value = u128::from_str_radix(digits, radix as u32).ok()?; | 576 | } |
569 | Some((radix, value)) | 577 | |
578 | pub fn suffix(&self) -> Option<&str> { | ||
579 | let text = self.text(); | ||
580 | // FIXME: don't check a fixed set of suffixes, `1_0_1___lol` is valid | ||
581 | // syntax, suffix is `lol`. | ||
582 | ast::IntNumber::SUFFIXES.iter().find_map(|suffix| { | ||
583 | if text.ends_with(suffix) { | ||
584 | return Some(&text[text.len() - suffix.len()..]); | ||
585 | } | ||
586 | None | ||
587 | }) | ||
570 | } | 588 | } |
571 | } | 589 | } |
572 | 590 | ||
@@ -586,27 +604,6 @@ impl Radix { | |||
586 | pub const ALL: &'static [Radix] = | 604 | pub const ALL: &'static [Radix] = |
587 | &[Radix::Binary, Radix::Octal, Radix::Decimal, Radix::Hexadecimal]; | 605 | &[Radix::Binary, Radix::Octal, Radix::Decimal, Radix::Hexadecimal]; |
588 | 606 | ||
589 | fn identify(literal_text: &str) -> Option<Self> { | ||
590 | // We cannot express a literal in anything other than decimal in under 3 characters, so we return here if possible. | ||
591 | if literal_text.len() < 3 && literal_text.chars().all(|c| c.is_digit(10)) { | ||
592 | return Some(Self::Decimal); | ||
593 | } | ||
594 | |||
595 | let res = match &literal_text[..2] { | ||
596 | "0b" => Radix::Binary, | ||
597 | "0o" => Radix::Octal, | ||
598 | "0x" => Radix::Hexadecimal, | ||
599 | _ => Radix::Decimal, | ||
600 | }; | ||
601 | |||
602 | // Checks that all characters after the base prefix are all valid digits for that base. | ||
603 | if literal_text[res.prefix_len()..].chars().all(|c| c.is_digit(res as u32)) { | ||
604 | Some(res) | ||
605 | } else { | ||
606 | None | ||
607 | } | ||
608 | } | ||
609 | |||
610 | const fn prefix_len(&self) -> usize { | 607 | const fn prefix_len(&self) -> usize { |
611 | match self { | 608 | match self { |
612 | Self::Decimal => 0, | 609 | Self::Decimal => 0, |