mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-26 04:53:34 +00:00
Implement slice pattern AST > HIR lowering
This commit is contained in:
parent
3e1d97790b
commit
a3b104aa6d
8 changed files with 64 additions and 13 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1070,6 +1070,7 @@ dependencies = [
|
||||||
"drop_bomb",
|
"drop_bomb",
|
||||||
"either",
|
"either",
|
||||||
"insta",
|
"insta",
|
||||||
|
"itertools",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"ra_arena",
|
"ra_arena",
|
||||||
|
|
|
@ -14,6 +14,7 @@ rustc-hash = "1.0"
|
||||||
either = "1.5"
|
either = "1.5"
|
||||||
anymap = "0.12"
|
anymap = "0.12"
|
||||||
drop_bomb = "0.1.4"
|
drop_bomb = "0.1.4"
|
||||||
|
itertools = "0.8.2"
|
||||||
|
|
||||||
ra_arena = { path = "../ra_arena" }
|
ra_arena = { path = "../ra_arena" }
|
||||||
ra_db = { path = "../ra_db" }
|
ra_db = { path = "../ra_db" }
|
||||||
|
|
|
@ -8,7 +8,7 @@ use ra_arena::Arena;
|
||||||
use ra_syntax::{
|
use ra_syntax::{
|
||||||
ast::{
|
ast::{
|
||||||
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
|
self, ArgListOwner, ArrayExprKind, LiteralKind, LoopBodyOwner, ModuleItemOwner, NameOwner,
|
||||||
TypeAscriptionOwner,
|
SlicePatComponents, TypeAscriptionOwner,
|
||||||
},
|
},
|
||||||
AstNode, AstPtr,
|
AstNode, AstPtr,
|
||||||
};
|
};
|
||||||
|
@ -591,7 +591,7 @@ where
|
||||||
let args = p.args().map(|p| self.collect_pat(p)).collect();
|
let args = p.args().map(|p| self.collect_pat(p)).collect();
|
||||||
Pat::Tuple(args)
|
Pat::Tuple(args)
|
||||||
}
|
}
|
||||||
ast::Pat::PlaceholderPat(_) => Pat::Wild,
|
ast::Pat::PlaceholderPat(_) | ast::Pat::DotDotPat(_) => Pat::Wild,
|
||||||
ast::Pat::RecordPat(p) => {
|
ast::Pat::RecordPat(p) => {
|
||||||
let path = p.path().and_then(|path| self.expander.parse_path(path));
|
let path = p.path().and_then(|path| self.expander.parse_path(path));
|
||||||
let record_field_pat_list =
|
let record_field_pat_list =
|
||||||
|
@ -616,12 +616,20 @@ where
|
||||||
|
|
||||||
Pat::Record { path, args: fields }
|
Pat::Record { path, args: fields }
|
||||||
}
|
}
|
||||||
|
ast::Pat::SlicePat(p) => {
|
||||||
|
let SlicePatComponents { prefix, slice, suffix } = p.components();
|
||||||
|
|
||||||
|
Pat::Slice {
|
||||||
|
prefix: prefix.into_iter().map(|p| self.collect_pat(p)).collect(),
|
||||||
|
slice: slice.map(|p| self.collect_pat(p)),
|
||||||
|
suffix: suffix.into_iter().map(|p| self.collect_pat(p)).collect(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: implement
|
// FIXME: implement
|
||||||
ast::Pat::DotDotPat(_) => Pat::Missing,
|
|
||||||
ast::Pat::BoxPat(_) => Pat::Missing,
|
ast::Pat::BoxPat(_) => Pat::Missing,
|
||||||
ast::Pat::LiteralPat(_) => Pat::Missing,
|
ast::Pat::LiteralPat(_) => Pat::Missing,
|
||||||
ast::Pat::SlicePat(_) | ast::Pat::RangePat(_) => Pat::Missing,
|
ast::Pat::RangePat(_) => Pat::Missing,
|
||||||
};
|
};
|
||||||
let ptr = AstPtr::new(&pat);
|
let ptr = AstPtr::new(&pat);
|
||||||
self.alloc_pat(pattern, Either::Left(ptr))
|
self.alloc_pat(pattern, Either::Left(ptr))
|
||||||
|
|
|
@ -393,7 +393,7 @@ pub enum Pat {
|
||||||
},
|
},
|
||||||
Slice {
|
Slice {
|
||||||
prefix: Vec<PatId>,
|
prefix: Vec<PatId>,
|
||||||
rest: Option<PatId>,
|
slice: Option<PatId>,
|
||||||
suffix: Vec<PatId>,
|
suffix: Vec<PatId>,
|
||||||
},
|
},
|
||||||
Path(Path),
|
Path(Path),
|
||||||
|
@ -424,8 +424,8 @@ impl Pat {
|
||||||
args.iter().copied().for_each(f);
|
args.iter().copied().for_each(f);
|
||||||
}
|
}
|
||||||
Pat::Ref { pat, .. } => f(*pat),
|
Pat::Ref { pat, .. } => f(*pat),
|
||||||
Pat::Slice { prefix, rest, suffix } => {
|
Pat::Slice { prefix, slice, suffix } => {
|
||||||
let total_iter = prefix.iter().chain(rest.iter()).chain(suffix.iter());
|
let total_iter = prefix.iter().chain(slice.iter()).chain(suffix.iter());
|
||||||
total_iter.copied().for_each(f);
|
total_iter.copied().for_each(f);
|
||||||
}
|
}
|
||||||
Pat::Record { args, .. } => {
|
Pat::Record { args, .. } => {
|
||||||
|
|
|
@ -18,7 +18,8 @@ use crate::{
|
||||||
pub use self::{
|
pub use self::{
|
||||||
expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
|
expr_extensions::{ArrayExprKind, BinOp, ElseBranch, LiteralKind, PrefixOp, RangeOp},
|
||||||
extensions::{
|
extensions::{
|
||||||
FieldKind, PathSegmentKind, SelfParamKind, StructKind, TypeBoundKind, VisibilityKind,
|
FieldKind, PathSegmentKind, SelfParamKind, SlicePatComponents, StructKind, TypeBoundKind,
|
||||||
|
VisibilityKind,
|
||||||
},
|
},
|
||||||
generated::*,
|
generated::*,
|
||||||
tokens::*,
|
tokens::*,
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
//! Various extension methods to ast Nodes, which are hard to code-generate.
|
//! Various extension methods to ast Nodes, which are hard to code-generate.
|
||||||
//! Extensions for various expressions live in a sibling `expr_extensions` module.
|
//! Extensions for various expressions live in a sibling `expr_extensions` module.
|
||||||
|
|
||||||
|
use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode},
|
ast::{self, child_opt, children, AstNode, AttrInput, SyntaxNode},
|
||||||
SmolStr, SyntaxElement,
|
SmolStr, SyntaxElement,
|
||||||
|
@ -293,6 +295,40 @@ impl ast::BindPat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct SlicePatComponents {
|
||||||
|
pub prefix: Vec<ast::Pat>,
|
||||||
|
pub slice: Option<ast::Pat>,
|
||||||
|
pub suffix: Vec<ast::Pat>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ast::SlicePat {
|
||||||
|
pub fn components(&self) -> SlicePatComponents {
|
||||||
|
let mut args = self.args().peekable();
|
||||||
|
let prefix = args
|
||||||
|
.peeking_take_while(|p| match p {
|
||||||
|
ast::Pat::DotDotPat(_) => false,
|
||||||
|
ast::Pat::BindPat(bp) => match bp.pat() {
|
||||||
|
Some(ast::Pat::DotDotPat(_)) => false,
|
||||||
|
_ => true,
|
||||||
|
},
|
||||||
|
ast::Pat::RefPat(rp) => match rp.pat() {
|
||||||
|
Some(ast::Pat::DotDotPat(_)) => false,
|
||||||
|
Some(ast::Pat::BindPat(bp)) => match bp.pat() {
|
||||||
|
Some(ast::Pat::DotDotPat(_)) => false,
|
||||||
|
_ => true,
|
||||||
|
},
|
||||||
|
_ => true,
|
||||||
|
},
|
||||||
|
_ => true,
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let slice = args.next();
|
||||||
|
let suffix = args.collect();
|
||||||
|
|
||||||
|
SlicePatComponents { prefix, slice, suffix }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ast::PointerType {
|
impl ast::PointerType {
|
||||||
pub fn is_mut(&self) -> bool {
|
pub fn is_mut(&self) -> bool {
|
||||||
self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
|
self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
|
||||||
|
|
|
@ -2063,7 +2063,11 @@ impl AstNode for SlicePat {
|
||||||
&self.syntax
|
&self.syntax
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl SlicePat {}
|
impl SlicePat {
|
||||||
|
pub fn args(&self) -> AstChildren<Pat> {
|
||||||
|
AstChildren::new(&self.syntax)
|
||||||
|
}
|
||||||
|
}
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct RangePat {
|
pub struct RangePat {
|
||||||
pub(crate) syntax: SyntaxNode,
|
pub(crate) syntax: SyntaxNode,
|
||||||
|
|
|
@ -415,14 +415,14 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
pats: [Pat],
|
pats: [Pat],
|
||||||
guard: MatchGuard,
|
guard: MatchGuard,
|
||||||
Expr,
|
Expr,
|
||||||
}
|
}
|
||||||
struct MatchGuard { Expr }
|
struct MatchGuard { Expr }
|
||||||
|
|
||||||
struct RecordLit { Path, RecordFieldList }
|
struct RecordLit { Path, RecordFieldList }
|
||||||
struct RecordFieldList {
|
struct RecordFieldList {
|
||||||
fields: [RecordField],
|
fields: [RecordField],
|
||||||
spread: Expr,
|
spread: Expr,
|
||||||
}
|
}
|
||||||
struct RecordField { NameRef, Expr }
|
struct RecordField { NameRef, Expr }
|
||||||
|
|
||||||
struct RefPat { Pat }
|
struct RefPat { Pat }
|
||||||
|
@ -430,8 +430,8 @@ pub(crate) const AST_SRC: AstSrc = AstSrc {
|
||||||
struct BindPat: NameOwner { Pat }
|
struct BindPat: NameOwner { Pat }
|
||||||
struct PlaceholderPat { }
|
struct PlaceholderPat { }
|
||||||
struct DotDotPat { }
|
struct DotDotPat { }
|
||||||
struct PathPat { Path }
|
struct PathPat { Path }
|
||||||
struct SlicePat {}
|
struct SlicePat { args: [Pat] }
|
||||||
struct RangePat {}
|
struct RangePat {}
|
||||||
struct LiteralPat { Literal }
|
struct LiteralPat { Literal }
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue