From 5db789df9c767985a564a31cc593ce7f5964100e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 6 Nov 2020 22:52:22 +0100 Subject: Cleanup API --- .../src/handlers/convert_integer_literal.rs | 6 +- crates/hir_def/src/body/lower.rs | 21 +++---- crates/syntax/src/ast/expr_ext.rs | 64 ++++++---------------- crates/syntax/src/ast/token_ext.rs | 32 +++++++---- crates/syntax/src/validation.rs | 57 +++++++++---------- 5 files changed, 84 insertions(+), 96 deletions(-) diff --git a/crates/assists/src/handlers/convert_integer_literal.rs b/crates/assists/src/handlers/convert_integer_literal.rs index 5957834d3..1094ed3f3 100644 --- a/crates/assists/src/handlers/convert_integer_literal.rs +++ b/crates/assists/src/handlers/convert_integer_literal.rs @@ -14,7 +14,11 @@ use crate::{AssistContext, AssistId, AssistKind, Assists, GroupLabel}; // const _: i32 = 0b1010; // ``` pub(crate) fn convert_integer_literal(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { - let literal = ctx.find_node_at_offset::()?.as_int_number()?; + let literal = ctx.find_node_at_offset::()?; + let literal = match literal.kind() { + ast::LiteralKind::IntNumber(it) => it, + _ => return None, + }; let radix = literal.radix(); let value = literal.value()?; let suffix = literal.suffix(); diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 1deaa90f2..cd7958746 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -953,18 +953,19 @@ impl From for BinaryOp { impl From for Literal { fn from(ast_lit_kind: ast::LiteralKind) -> Self { match ast_lit_kind { - LiteralKind::IntNumber { suffix } => { - let known_name = suffix.and_then(|it| BuiltinInt::from_suffix(&it)); - - Literal::Int(Default::default(), known_name) + LiteralKind::IntNumber(lit) => { + if let Some(float_suffix) = lit.suffix().and_then(BuiltinFloat::from_suffix) { + return Literal::Float(Default::default(), Some(float_suffix)); + } + let ty = lit.suffix().and_then(|it| BuiltinInt::from_suffix(&it)); + Literal::Int(Default::default(), ty) } - LiteralKind::FloatNumber { suffix } => { - let known_name = suffix.and_then(|it| BuiltinFloat::from_suffix(&it)); - - Literal::Float(Default::default(), known_name) + LiteralKind::FloatNumber(lit) => { + let ty = lit.suffix().and_then(|it| BuiltinFloat::from_suffix(&it)); + Literal::Float(Default::default(), ty) } - LiteralKind::ByteString => Literal::ByteString(Default::default()), - LiteralKind::String => Literal::String(Default::default()), + LiteralKind::ByteString(_) => Literal::ByteString(Default::default()), + LiteralKind::String(_) => Literal::String(Default::default()), LiteralKind::Byte => Literal::Int(Default::default(), Some(BuiltinInt::U8)), LiteralKind::Bool(val) => Literal::Bool(val), LiteralKind::Char => Literal::Char(Default::default()), diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs index eb44bb2ab..9253c97d0 100644 --- a/crates/syntax/src/ast/expr_ext.rs +++ b/crates/syntax/src/ast/expr_ext.rs @@ -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 }, - FloatNumber { suffix: Option }, 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::cast(self.token()) - } - - pub fn as_string(&self) -> Option { - ast::String::cast(self.token()) - } - pub fn as_byte_string(&self) -> Option { - ast::ByteString::cast(self.token()) - } - - fn find_suffix(text: &str, possible_suffixes: &[&str]) -> Option { - 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!(), diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs index bf0035986..e4e512f2e 100644 --- a/crates/syntax/src/ast/token_ext.rs +++ b/crates/syntax/src/ast/token_ext.rs @@ -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, diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs index 62a37c50a..6f45149bf 100644 --- a/crates/syntax/src/validation.rs +++ b/crates/syntax/src/validation.rs @@ -4,7 +4,7 @@ mod block; use crate::{ algo, ast, match_ast, AstNode, SyntaxError, - SyntaxKind::{BYTE, CHAR, CONST, FN, INT_NUMBER, TYPE_ALIAS}, + SyntaxKind::{CONST, FN, INT_NUMBER, TYPE_ALIAS}, SyntaxNode, SyntaxToken, TextSize, T, }; use rowan::Direction; @@ -121,41 +121,42 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec) { acc.push(SyntaxError::new_at_offset(rustc_unescape_error_to_string(err), off)); }; - if let Some(s) = literal.as_string() { - if !s.is_raw() { - if let Some(without_quotes) = unquote(text, 1, '"') { - unescape_literal(without_quotes, Mode::Str, &mut |range, char| { - if let Err(err) = char { - push_err(1, (range.start, err)); - } - }) - } - } - } - if let Some(s) = literal.as_byte_string() { - if !s.is_raw() { - if let Some(without_quotes) = unquote(text, 2, '"') { - unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| { - if let Err(err) = char { - push_err(2, (range.start, err)); - } - }) + match literal.kind() { + ast::LiteralKind::String(s) => { + if !s.is_raw() { + if let Some(without_quotes) = unquote(text, 1, '"') { + unescape_literal(without_quotes, Mode::Str, &mut |range, char| { + if let Err(err) = char { + push_err(1, (range.start, err)); + } + }) + } } } - } - - match token.kind() { - BYTE => { - if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) { - push_err(2, e); + ast::LiteralKind::ByteString(s) => { + if !s.is_raw() { + if let Some(without_quotes) = unquote(text, 2, '"') { + unescape_byte_literal(without_quotes, Mode::ByteStr, &mut |range, char| { + if let Err(err) = char { + push_err(2, (range.start, err)); + } + }) + } } } - CHAR => { + ast::LiteralKind::Char => { if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) { push_err(1, e); } } - _ => (), + ast::LiteralKind::Byte => { + if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) { + push_err(2, e); + } + } + ast::LiteralKind::IntNumber(_) + | ast::LiteralKind::FloatNumber(_) + | ast::LiteralKind::Bool(_) => {} } } -- cgit v1.2.3