mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
Auto merge of #12157 - lnicola:lower-char-byte-literals, r=Veykril
feat: Lower values of char and byte literals Closes #12137
This commit is contained in:
commit
e789d73424
8 changed files with 178 additions and 11 deletions
|
@ -983,9 +983,11 @@ impl From<ast::LiteralKind> for Literal {
|
|||
let text = s.value().map(Box::from).unwrap_or_else(Default::default);
|
||||
Literal::String(text)
|
||||
}
|
||||
LiteralKind::Byte => Literal::Uint(Default::default(), Some(BuiltinUint::U8)),
|
||||
LiteralKind::Byte(b) => {
|
||||
Literal::Uint(b.value().unwrap_or_default() as u128, Some(BuiltinUint::U8))
|
||||
}
|
||||
LiteralKind::Char(c) => Literal::Char(c.value().unwrap_or_default()),
|
||||
LiteralKind::Bool(val) => Literal::Bool(val),
|
||||
LiteralKind::Char => Literal::Char(Default::default()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3507,6 +3507,94 @@ const FOO$0: &str = "bar";
|
|||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
// show char literal
|
||||
check(
|
||||
r#"
|
||||
/// This is a doc
|
||||
const FOO$0: char = 'a';
|
||||
"#,
|
||||
expect![[r#"
|
||||
*FOO*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
const FOO: char = 'a'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
// show escaped char literal
|
||||
check(
|
||||
r#"
|
||||
/// This is a doc
|
||||
const FOO$0: char = '\x61';
|
||||
"#,
|
||||
expect![[r#"
|
||||
*FOO*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
const FOO: char = 'a'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
// show byte literal
|
||||
check(
|
||||
r#"
|
||||
/// This is a doc
|
||||
const FOO$0: u8 = b'a';
|
||||
"#,
|
||||
expect![[r#"
|
||||
*FOO*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
const FOO: u8 = 97 (0x61)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
// show escaped byte literal
|
||||
check(
|
||||
r#"
|
||||
/// This is a doc
|
||||
const FOO$0: u8 = b'\x61';
|
||||
"#,
|
||||
expect![[r#"
|
||||
*FOO*
|
||||
|
||||
```rust
|
||||
test
|
||||
```
|
||||
|
||||
```rust
|
||||
const FOO: u8 = 97 (0x61)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
This is a doc
|
||||
"#]],
|
||||
);
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
//!
|
||||
//! The `cli` submodule implements some batch-processing analysis, primarily as
|
||||
//! a debugging aid.
|
||||
#![recursion_limit = "512"]
|
||||
|
||||
pub mod cli;
|
||||
|
||||
|
|
|
@ -283,8 +283,8 @@ pub enum LiteralKind {
|
|||
ByteString(ast::ByteString),
|
||||
IntNumber(ast::IntNumber),
|
||||
FloatNumber(ast::FloatNumber),
|
||||
Char,
|
||||
Byte,
|
||||
Char(ast::Char),
|
||||
Byte(ast::Byte),
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
|
@ -312,12 +312,16 @@ impl ast::Literal {
|
|||
if let Some(t) = ast::ByteString::cast(token.clone()) {
|
||||
return LiteralKind::ByteString(t);
|
||||
}
|
||||
if let Some(t) = ast::Char::cast(token.clone()) {
|
||||
return LiteralKind::Char(t);
|
||||
}
|
||||
if let Some(t) = ast::Byte::cast(token.clone()) {
|
||||
return LiteralKind::Byte(t);
|
||||
}
|
||||
|
||||
match token.kind() {
|
||||
T![true] => LiteralKind::Bool(true),
|
||||
T![false] => LiteralKind::Bool(false),
|
||||
CHAR => LiteralKind::Char,
|
||||
BYTE => LiteralKind::Byte,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -132,6 +132,48 @@ impl AstToken for FloatNumber {
|
|||
fn syntax(&self) -> &SyntaxToken { &self.syntax }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Char {
|
||||
pub(crate) syntax: SyntaxToken,
|
||||
}
|
||||
impl std::fmt::Display for Char {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.syntax, f)
|
||||
}
|
||||
}
|
||||
impl AstToken for Char {
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == CHAR }
|
||||
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) {
|
||||
Some(Self { syntax })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken { &self.syntax }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Byte {
|
||||
pub(crate) syntax: SyntaxToken,
|
||||
}
|
||||
impl std::fmt::Display for Byte {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
std::fmt::Display::fmt(&self.syntax, f)
|
||||
}
|
||||
}
|
||||
impl AstToken for Byte {
|
||||
fn can_cast(kind: SyntaxKind) -> bool { kind == BYTE }
|
||||
fn cast(syntax: SyntaxToken) -> Option<Self> {
|
||||
if Self::can_cast(syntax.kind()) {
|
||||
Some(Self { syntax })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn syntax(&self) -> &SyntaxToken { &self.syntax }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Ident {
|
||||
pub(crate) syntax: SyntaxToken,
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
use std::borrow::Cow;
|
||||
|
||||
use rustc_lexer::unescape::{unescape_literal, Mode};
|
||||
use rustc_lexer::unescape::{unescape_byte, unescape_char, unescape_literal, Mode};
|
||||
|
||||
use crate::{
|
||||
ast::{self, AstToken},
|
||||
|
@ -406,3 +406,35 @@ mod tests {
|
|||
check_string_value(r"C:\\Windows\\System32\\", "C:\\Windows\\System32\\");
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::Char {
|
||||
pub fn value(&self) -> Option<char> {
|
||||
let mut text = self.text();
|
||||
if text.starts_with('\'') {
|
||||
text = &text[1..];
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
if text.ends_with('\'') {
|
||||
text = &text[0..text.len() - 1];
|
||||
}
|
||||
|
||||
unescape_char(text).ok()
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::Byte {
|
||||
pub fn value(&self) -> Option<u8> {
|
||||
let mut text = self.text();
|
||||
if text.starts_with("b\'") {
|
||||
text = &text[2..];
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
if text.ends_with('\'') {
|
||||
text = &text[0..text.len() - 1];
|
||||
}
|
||||
|
||||
unescape_byte(text).ok()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -585,7 +585,7 @@ impl Field {
|
|||
|
||||
fn lower(grammar: &Grammar) -> AstSrc {
|
||||
let mut res = AstSrc {
|
||||
tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Ident"
|
||||
tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Char Byte Ident"
|
||||
.split_ascii_whitespace()
|
||||
.map(|it| it.to_string())
|
||||
.collect::<Vec<_>>(),
|
||||
|
|
|
@ -151,12 +151,12 @@ fn validate_literal(literal: ast::Literal, acc: &mut Vec<SyntaxError>) {
|
|||
}
|
||||
}
|
||||
}
|
||||
ast::LiteralKind::Char => {
|
||||
ast::LiteralKind::Char(_) => {
|
||||
if let Some(Err(e)) = unquote(text, 1, '\'').map(unescape_char) {
|
||||
push_err(1, e);
|
||||
}
|
||||
}
|
||||
ast::LiteralKind::Byte => {
|
||||
ast::LiteralKind::Byte(_) => {
|
||||
if let Some(Err(e)) = unquote(text, 2, '\'').map(unescape_byte) {
|
||||
push_err(2, e);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue