mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 21:05:02 +00:00
Wrap float literals in their own node
This commit is contained in:
parent
2d5d16f18c
commit
502c519e7d
13 changed files with 113 additions and 49 deletions
|
@ -282,7 +282,7 @@ pub enum LiteralKind {
|
|||
String(ast::String),
|
||||
ByteString(ast::ByteString),
|
||||
IntNumber(ast::IntNumber),
|
||||
FloatNumber(ast::FloatNumber),
|
||||
FloatNumber(ast::FloatLiteral),
|
||||
Char(ast::Char),
|
||||
Byte(ast::Byte),
|
||||
Bool(bool),
|
||||
|
@ -297,16 +297,17 @@ impl ast::Literal {
|
|||
}
|
||||
pub fn kind(&self) -> LiteralKind {
|
||||
let token = match self.value() {
|
||||
rowan::NodeOrToken::Node(_node) => unreachable!(),
|
||||
rowan::NodeOrToken::Node(node) => {
|
||||
return LiteralKind::FloatNumber(
|
||||
ast::FloatLiteral::cast(node).expect("unreachable"),
|
||||
);
|
||||
}
|
||||
rowan::NodeOrToken::Token(token) => 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);
|
||||
}
|
||||
|
@ -326,6 +327,26 @@ impl ast::Literal {
|
|||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> Option<ast::String> {
|
||||
match self.kind() {
|
||||
LiteralKind::String(it) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_byte_string(&self) -> Option<ast::ByteString> {
|
||||
match self.kind() {
|
||||
LiteralKind::ByteString(it) => Some(it),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::FloatLiteral {
|
||||
pub fn suffix(&self) -> Option<String> {
|
||||
ast::FloatNumber::cast(self.syntax().last_token()?)?.suffix().map(|s| s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
pub enum BlockModifier {
|
||||
|
|
|
@ -1085,6 +1085,16 @@ impl UnderscoreExpr {
|
|||
pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct FloatLiteral {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
}
|
||||
impl FloatLiteral {
|
||||
pub fn float_number_token(&self) -> Option<SyntaxToken> {
|
||||
support::token(&self.syntax, T![float_number])
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct StmtList {
|
||||
pub(crate) syntax: SyntaxNode,
|
||||
|
@ -2719,6 +2729,17 @@ impl AstNode for UnderscoreExpr {
|
|||
}
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
}
|
||||
impl AstNode for FloatLiteral {
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == FLOAT_LITERAL }
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) {
|
||||
Some(Self { syntax })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxNode { &self.syntax }
|
||||
}
|
||||
impl AstNode for StmtList {
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == STMT_LIST }
|
||||
fn cast(syntax: SyntaxNode) -> Option<Self> {
|
||||
|
@ -4608,6 +4629,11 @@ impl std::fmt::Display for UnderscoreExpr {
|
|||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
}
|
||||
}
|
||||
impl std::fmt::Display for FloatLiteral {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
}
|
||||
}
|
||||
impl std::fmt::Display for StmtList {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(self.syntax(), f)
|
||||
|
|
|
@ -799,6 +799,11 @@ pub fn struct_(
|
|||
))
|
||||
}
|
||||
|
||||
pub fn literal(text: &str) -> ast::Literal {
|
||||
assert_eq!(text.trim(), text);
|
||||
ast_from_text(&format!("fn f() {{ let _ = {}; }}", text))
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn ast_from_text<N: AstNode>(text: &str) -> N {
|
||||
let parse = SourceFile::parse(text);
|
||||
|
@ -827,7 +832,7 @@ pub fn token(kind: SyntaxKind) -> SyntaxToken {
|
|||
pub mod tokens {
|
||||
use once_cell::sync::Lazy;
|
||||
|
||||
use crate::{ast, AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken};
|
||||
use crate::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken};
|
||||
|
||||
pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| {
|
||||
SourceFile::parse(
|
||||
|
@ -858,12 +863,6 @@ pub mod tokens {
|
|||
sf.syntax().first_child_or_token().unwrap().into_token().unwrap()
|
||||
}
|
||||
|
||||
pub fn literal(text: &str) -> SyntaxToken {
|
||||
assert_eq!(text.trim(), text);
|
||||
let lit: ast::Literal = super::ast_from_text(&format!("fn f() {{ let _ = {}; }}", text));
|
||||
lit.syntax().first_child_or_token().unwrap().into_token().unwrap()
|
||||
}
|
||||
|
||||
pub fn single_newline() -> SyntaxToken {
|
||||
let res = SOURCE_FILE
|
||||
.tree()
|
||||
|
|
|
@ -355,14 +355,24 @@ impl Radix {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ast::{self, make, FloatNumber, IntNumber};
|
||||
use crate::ast::{self, make};
|
||||
|
||||
fn check_float_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) {
|
||||
assert_eq!(FloatNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into());
|
||||
let suffix = match make::literal(lit).kind() {
|
||||
ast::LiteralKind::FloatNumber(f) => f.suffix(),
|
||||
// `1f32` lexes as an INT_NUMBER
|
||||
ast::LiteralKind::IntNumber(i) => i.suffix().map(|s| s.to_string()),
|
||||
e => unreachable!("{e:?}"),
|
||||
};
|
||||
assert_eq!(suffix.as_deref(), expected.into());
|
||||
}
|
||||
|
||||
fn check_int_suffix<'a>(lit: &str, expected: impl Into<Option<&'a str>>) {
|
||||
assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.suffix(), expected.into());
|
||||
let i = match make::literal(lit).kind() {
|
||||
ast::LiteralKind::IntNumber(i) => i,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
assert_eq!(i.suffix(), expected.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -390,12 +400,11 @@ mod tests {
|
|||
}
|
||||
|
||||
fn check_string_value<'a>(lit: &str, expected: impl Into<Option<&'a str>>) {
|
||||
assert_eq!(
|
||||
ast::String { syntax: make::tokens::literal(&format!("\"{}\"", lit)) }
|
||||
.value()
|
||||
.as_deref(),
|
||||
expected.into()
|
||||
);
|
||||
let s = match make::literal(&format!("\"{}\"", lit)).kind() {
|
||||
ast::LiteralKind::String(s) => s,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
assert_eq!(s.value().as_deref(), expected.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue