mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-28 04:44:57 +00:00
Merge commit 'a911652360
' into sync-from-ra
This commit is contained in:
parent
0661390ad4
commit
e4866b6ddb
315 changed files with 7088 additions and 4415 deletions
|
@ -1,6 +1,6 @@
|
|||
//! Structural editing for ast.
|
||||
|
||||
use std::iter::{empty, successors};
|
||||
use std::iter::{empty, once, successors};
|
||||
|
||||
use parser::{SyntaxKind, T};
|
||||
|
||||
|
@ -530,6 +530,25 @@ impl ast::UseTree {
|
|||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Wraps the use tree in use tree list with no top level path (if it isn't already).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `foo::bar` -> `{foo::bar}`
|
||||
///
|
||||
/// `{foo::bar}` -> `{foo::bar}`
|
||||
pub fn wrap_in_tree_list(&self) {
|
||||
if self.path().is_none() {
|
||||
return;
|
||||
}
|
||||
let subtree = self.clone_subtree().clone_for_update();
|
||||
ted::remove_all_iter(self.syntax().children_with_tokens());
|
||||
ted::append_child(
|
||||
self.syntax(),
|
||||
make::use_tree_list(once(subtree)).clone_for_update().syntax(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::UseTreeList {
|
||||
|
|
|
@ -595,6 +595,9 @@ pub fn expr_macro_call(f: ast::Expr, arg_list: ast::ArgList) -> ast::Expr {
|
|||
pub fn expr_ref(expr: ast::Expr, exclusive: bool) -> ast::Expr {
|
||||
expr_from_text(&if exclusive { format!("&mut {expr}") } else { format!("&{expr}") })
|
||||
}
|
||||
pub fn expr_reborrow(expr: ast::Expr) -> ast::Expr {
|
||||
expr_from_text(&format!("&mut *{expr}"))
|
||||
}
|
||||
pub fn expr_closure(pats: impl IntoIterator<Item = ast::Param>, expr: ast::Expr) -> ast::Expr {
|
||||
let params = pats.into_iter().join(", ");
|
||||
expr_from_text(&format!("|{params}| {expr}"))
|
||||
|
|
|
@ -53,6 +53,12 @@ fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl ast::Abi {
|
||||
pub fn abi_string(&self) -> Option<ast::String> {
|
||||
support::token(&self.syntax, SyntaxKind::STRING).and_then(ast::String::cast)
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::HasModuleItem for ast::StmtList {}
|
||||
|
||||
impl ast::BlockExpr {
|
||||
|
@ -327,6 +333,14 @@ impl ast::UseTree {
|
|||
pub fn parent_use_tree_list(&self) -> Option<ast::UseTreeList> {
|
||||
self.syntax().parent().and_then(ast::UseTreeList::cast)
|
||||
}
|
||||
|
||||
pub fn top_use_tree(&self) -> ast::UseTree {
|
||||
let mut this = self.clone();
|
||||
while let Some(use_tree_list) = this.parent_use_tree_list() {
|
||||
this = use_tree_list.parent_use_tree();
|
||||
}
|
||||
this
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::UseTreeList {
|
||||
|
@ -356,8 +370,12 @@ impl ast::UseTreeList {
|
|||
let remove_brace_in_use_tree_list = |u: &ast::UseTreeList| {
|
||||
let use_tree_count = u.use_trees().count();
|
||||
if use_tree_count == 1 {
|
||||
u.l_curly_token().map(ted::remove);
|
||||
u.r_curly_token().map(ted::remove);
|
||||
if let Some(a) = u.l_curly_token() {
|
||||
ted::remove(a)
|
||||
}
|
||||
if let Some(a) = u.r_curly_token() {
|
||||
ted::remove(a)
|
||||
}
|
||||
u.comma().for_each(ted::remove);
|
||||
}
|
||||
};
|
||||
|
@ -440,6 +458,12 @@ impl ast::Struct {
|
|||
}
|
||||
}
|
||||
|
||||
impl ast::Union {
|
||||
pub fn kind(&self) -> StructKind {
|
||||
StructKind::from_node(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ast::RecordExprField {
|
||||
pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> {
|
||||
let candidate = Self::for_name_ref(field_name)?;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
//! There are many AstNodes, but only a few tokens, so we hand-write them here.
|
||||
|
||||
use std::borrow::Cow;
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
num::{ParseFloatError, ParseIntError},
|
||||
};
|
||||
|
||||
use rustc_lexer::unescape::{
|
||||
unescape_byte, unescape_c_string, unescape_char, unescape_literal, CStrUnit, Mode,
|
||||
|
@ -391,10 +394,9 @@ impl ast::IntNumber {
|
|||
(prefix, text, suffix)
|
||||
}
|
||||
|
||||
pub fn value(&self) -> Option<u128> {
|
||||
pub fn value(&self) -> Result<u128, ParseIntError> {
|
||||
let (_, text, _) = self.split_into_parts();
|
||||
let value = u128::from_str_radix(&text.replace('_', ""), self.radix() as u32).ok()?;
|
||||
Some(value)
|
||||
u128::from_str_radix(&text.replace('_', ""), self.radix() as u32)
|
||||
}
|
||||
|
||||
pub fn suffix(&self) -> Option<&str> {
|
||||
|
@ -445,9 +447,14 @@ impl ast::FloatNumber {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn value(&self) -> Option<f64> {
|
||||
pub fn value(&self) -> Result<f64, ParseFloatError> {
|
||||
let (text, _) = self.split_into_parts();
|
||||
text.replace('_', "").parse::<f64>().ok()
|
||||
text.replace('_', "").parse::<f64>()
|
||||
}
|
||||
|
||||
pub fn value_f32(&self) -> Result<f32, ParseFloatError> {
|
||||
let (text, _) = self.split_into_parts();
|
||||
text.replace('_', "").parse::<f32>()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,6 +478,38 @@ impl Radix {
|
|||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::ast::{self, make, FloatNumber, IntNumber};
|
||||
|
@ -484,12 +523,15 @@ mod tests {
|
|||
}
|
||||
|
||||
fn check_float_value(lit: &str, expected: impl Into<Option<f64>> + Copy) {
|
||||
assert_eq!(FloatNumber { syntax: make::tokens::literal(lit) }.value(), expected.into());
|
||||
assert_eq!(
|
||||
FloatNumber { syntax: make::tokens::literal(lit) }.value().ok(),
|
||||
expected.into()
|
||||
);
|
||||
assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.float_value(), expected.into());
|
||||
}
|
||||
|
||||
fn check_int_value(lit: &str, expected: impl Into<Option<u128>>) {
|
||||
assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.value(), expected.into());
|
||||
assert_eq!(IntNumber { syntax: make::tokens::literal(lit) }.value().ok(), expected.into());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -569,35 +611,3 @@ bcde", b"abcde",
|
|||
check_int_value("1_1_1_1_1_1", 111111);
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue