Cleanup API

This commit is contained in:
Aleksey Kladov 2020-11-06 22:52:22 +01:00
parent 7f12a1f225
commit 5db789df9c
5 changed files with 84 additions and 96 deletions

View file

@ -2,7 +2,7 @@
use crate::{
ast::{self, support, AstChildren, AstNode},
AstToken, SmolStr,
AstToken,
SyntaxKind::*,
SyntaxToken, T,
};
@ -298,12 +298,12 @@ impl ast::ArrayExpr {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum LiteralKind {
String,
ByteString,
String(ast::String),
ByteString(ast::ByteString),
IntNumber(ast::IntNumber),
FloatNumber(ast::FloatNumber),
Char,
Byte,
IntNumber { suffix: Option<SmolStr> },
FloatNumber { suffix: Option<SmolStr> },
Bool(bool),
}
@ -315,53 +315,25 @@ impl ast::Literal {
.and_then(|e| e.into_token())
.unwrap()
}
pub fn as_int_number(&self) -> Option<ast::IntNumber> {
ast::IntNumber::cast(self.token())
}
pub fn as_string(&self) -> Option<ast::String> {
ast::String::cast(self.token())
}
pub fn as_byte_string(&self) -> Option<ast::ByteString> {
ast::ByteString::cast(self.token())
}
fn find_suffix(text: &str, possible_suffixes: &[&str]) -> Option<SmolStr> {
possible_suffixes
.iter()
.find(|&suffix| text.ends_with(suffix))
.map(|&suffix| SmolStr::new(suffix))
}
pub fn kind(&self) -> LiteralKind {
let token = self.token();
if let Some(t) = ast::IntNumber::cast(token.clone()) {
return LiteralKind::IntNumber(t);
}
if let Some(t) = ast::FloatNumber::cast(token.clone()) {
return LiteralKind::FloatNumber(t);
}
if let Some(t) = ast::String::cast(token.clone()) {
return LiteralKind::String(t);
}
if let Some(t) = ast::ByteString::cast(token.clone()) {
return LiteralKind::ByteString(t);
}
match token.kind() {
INT_NUMBER => {
// FYI: there was a bug here previously, thus the if statement below is necessary.
// The lexer treats e.g. `1f64` as an integer literal. See
// https://github.com/rust-analyzer/rust-analyzer/issues/1592
// and the comments on the linked PR.
let text = token.text();
if let suffix @ Some(_) = Self::find_suffix(&text, &ast::FloatNumber::SUFFIXES) {
LiteralKind::FloatNumber { suffix }
} else {
LiteralKind::IntNumber {
suffix: Self::find_suffix(&text, &ast::IntNumber::SUFFIXES),
}
}
}
FLOAT_NUMBER => {
let text = token.text();
LiteralKind::FloatNumber {
suffix: Self::find_suffix(&text, &ast::FloatNumber::SUFFIXES),
}
}
STRING => LiteralKind::String,
T![true] => LiteralKind::Bool(true),
T![false] => LiteralKind::Bool(false),
BYTE_STRING => LiteralKind::ByteString,
CHAR => LiteralKind::Char,
BYTE => LiteralKind::Byte,
_ => unreachable!(),

View file

@ -517,10 +517,9 @@ impl HasFormatSpecifier for ast::String {
}
impl ast::IntNumber {
#[rustfmt::skip]
pub(crate) const SUFFIXES: &'static [&'static str] = &[
"u8", "u16", "u32", "u64", "u128", "usize",
"i8", "i16", "i32", "i64", "i128", "isize",
const SUFFIXES: &'static [&'static str] = &[
"u8", "u16", "u32", "u64", "u128", "usize", // Unsigned.
"i8", "i16", "i32", "i64", "i128", "isize", // Signed.
];
pub fn radix(&self) -> Radix {
@ -555,9 +554,24 @@ impl ast::IntNumber {
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| {
// FIXME: don't check a fixed set of suffixes, `1_0_1_l_o_l` is valid
// syntax, suffix is `l_o_l`.
ast::IntNumber::SUFFIXES.iter().chain(ast::FloatNumber::SUFFIXES.iter()).find_map(
|suffix| {
if text.ends_with(suffix) {
return Some(&text[text.len() - suffix.len()..]);
}
None
},
)
}
}
impl ast::FloatNumber {
const SUFFIXES: &'static [&'static str] = &["f32", "f64"];
pub fn suffix(&self) -> Option<&str> {
let text = self.text();
ast::FloatNumber::SUFFIXES.iter().find_map(|suffix| {
if text.ends_with(suffix) {
return Some(&text[text.len() - suffix.len()..]);
}
@ -566,10 +580,6 @@ impl ast::IntNumber {
}
}
impl ast::FloatNumber {
pub(crate) const SUFFIXES: &'static [&'static str] = &["f32", "f64"];
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum Radix {
Binary = 2,