From eb460333907a44c37bf7287b31c653877c3358c2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 6 Nov 2020 19:01:25 +0100 Subject: More orthogonal API --- crates/syntax/src/ast/token_ext.rs | 63 ++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 33 deletions(-) (limited to 'crates/syntax') 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 { } } +// FIXME: merge `ast::RawString` and `ast::String`. impl HasStringValue for ast::RawString { fn value(&self) -> Option> { let text = self.text().as_str(); @@ -544,29 +545,46 @@ impl ast::IntNumber { "i8", "i16", "i32", "i64", "i128", "isize", ]; - // FIXME: should probably introduce string token type? - // https://github.com/rust-analyzer/rust-analyzer/issues/6308 - pub fn value(&self) -> Option<(Radix, u128)> { + pub fn radix(&self) -> Radix { + match self.text().get(..2).unwrap_or_default() { + "0b" => Radix::Binary, + "0o" => Radix::Octal, + "0x" => Radix::Hexadecimal, + _ => Radix::Decimal, + } + } + + pub fn value(&self) -> Option { let token = self.syntax(); let mut text = token.text().as_str(); - for suffix in ast::IntNumber::SUFFIXES { - if let Some(without_suffix) = text.strip_suffix(suffix) { - text = without_suffix; - break; - } + if let Some(suffix) = self.suffix() { + text = &text[..text.len() - suffix.len()] } + let radix = self.radix(); + text = &text[radix.prefix_len()..]; + let buf; if text.contains("_") { buf = text.replace('_', ""); text = buf.as_str(); }; - let radix = Radix::identify(text)?; - let digits = &text[radix.prefix_len()..]; - let value = u128::from_str_radix(digits, radix as u32).ok()?; - Some((radix, value)) + let value = u128::from_str_radix(text, radix as u32).ok()?; + Some(value) + } + + pub fn suffix(&self) -> Option<&str> { + let text = self.text(); + // FIXME: don't check a fixed set of suffixes, `1_0_1___lol` is valid + // syntax, suffix is `lol`. + ast::IntNumber::SUFFIXES.iter().find_map(|suffix| { + if text.ends_with(suffix) { + return Some(&text[text.len() - suffix.len()..]); + } + None + }) } } @@ -586,27 +604,6 @@ impl Radix { pub const ALL: &'static [Radix] = &[Radix::Binary, Radix::Octal, Radix::Decimal, Radix::Hexadecimal]; - fn identify(literal_text: &str) -> Option { - // We cannot express a literal in anything other than decimal in under 3 characters, so we return here if possible. - if literal_text.len() < 3 && literal_text.chars().all(|c| c.is_digit(10)) { - return Some(Self::Decimal); - } - - let res = match &literal_text[..2] { - "0b" => Radix::Binary, - "0o" => Radix::Octal, - "0x" => Radix::Hexadecimal, - _ => Radix::Decimal, - }; - - // Checks that all characters after the base prefix are all valid digits for that base. - if literal_text[res.prefix_len()..].chars().all(|c| c.is_digit(res as u32)) { - Some(res) - } else { - None - } - } - const fn prefix_len(&self) -> usize { match self { Self::Decimal => 0, -- cgit v1.2.3