mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-09-26 11:59:49 +00:00
Create struct patterns up to the hir level
This commit is contained in:
parent
9c2d83a4c8
commit
ab5deb7811
5 changed files with 116 additions and 12 deletions
|
@ -329,13 +329,23 @@ impl Expr {
|
||||||
pub struct PatId(RawId);
|
pub struct PatId(RawId);
|
||||||
impl_arena_id!(PatId);
|
impl_arena_id!(PatId);
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
pub struct FieldPat {
|
||||||
|
name: Name,
|
||||||
|
pat: Option<PatId>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Close relative to rustc's hir::PatKind
|
/// Close relative to rustc's hir::PatKind
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub enum Pat {
|
pub enum Pat {
|
||||||
Missing, // do we need this?
|
Missing, // do we need this?
|
||||||
Wild,
|
Wild,
|
||||||
Tuple(Vec<PatId>),
|
Tuple(Vec<PatId>),
|
||||||
Struct, // TODO
|
Struct {
|
||||||
|
path: Option<Path>,
|
||||||
|
args: Vec<FieldPat>,
|
||||||
|
// TODO: 'ellipsis' option
|
||||||
|
},
|
||||||
Range {
|
Range {
|
||||||
start: ExprId,
|
start: ExprId,
|
||||||
end: ExprId,
|
end: ExprId,
|
||||||
|
@ -802,11 +812,30 @@ impl ExprCollector {
|
||||||
Pat::Tuple(args)
|
Pat::Tuple(args)
|
||||||
}
|
}
|
||||||
ast::PatKind::PlaceholderPat(_) => Pat::Wild,
|
ast::PatKind::PlaceholderPat(_) => Pat::Wild,
|
||||||
|
ast::PatKind::StructPat(p) => {
|
||||||
|
let path = p.path().and_then(Path::from_ast);
|
||||||
|
|
||||||
|
if let Some(field_list) = p.field_pat_list() {
|
||||||
|
let fields = field_list
|
||||||
|
.field_pats()
|
||||||
|
.into_iter()
|
||||||
|
.map(|f| FieldPat {
|
||||||
|
name: Name::new(f.ident),
|
||||||
|
pat: f.pat.as_ref().map(|p| self.collect_pat(p)),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Pat::Struct {
|
||||||
|
path: path,
|
||||||
|
args: fields,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Pat::Missing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: implement
|
// TODO: implement
|
||||||
ast::PatKind::FieldPatList(_)
|
ast::PatKind::SlicePat(_) | ast::PatKind::RangePat(_) => Pat::Missing,
|
||||||
| ast::PatKind::SlicePat(_)
|
|
||||||
| ast::PatKind::StructPat(_)
|
|
||||||
| ast::PatKind::RangePat(_) => Pat::Missing,
|
|
||||||
};
|
};
|
||||||
let syntax_ptr = LocalSyntaxPtr::new(pat.syntax());
|
let syntax_ptr = LocalSyntaxPtr::new(pat.syntax());
|
||||||
self.alloc_pat(pattern, syntax_ptr)
|
self.alloc_pat(pattern, syntax_ptr)
|
||||||
|
|
|
@ -877,6 +877,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
|
fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
|
||||||
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
let body = Arc::clone(&self.body); // avoid borrow checker problem
|
||||||
|
|
||||||
|
// FIXME: we can do some inference even if the expected ty isnt already
|
||||||
|
// of the right form
|
||||||
let ty = match (&body[pat], &expected.ty) {
|
let ty = match (&body[pat], &expected.ty) {
|
||||||
(Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
|
(Pat::Tuple(ref args), &Ty::Tuple(ref tuple_args))
|
||||||
if args.len() == tuple_args.len() =>
|
if args.len() == tuple_args.len() =>
|
||||||
|
|
|
@ -664,6 +664,75 @@ impl LiteralExpr {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// STRUCT_PAT@[20; 42)
|
||||||
|
// PATH@[20; 26)
|
||||||
|
// PATH_SEGMENT@[20; 26)
|
||||||
|
// NAME_REF@[20; 26)
|
||||||
|
// IDENT@[20; 26) "Strukt"
|
||||||
|
// WHITESPACE@[26; 27)
|
||||||
|
// FIELD_PAT_LIST@[27; 42)
|
||||||
|
// L_CURLY@[27; 28)
|
||||||
|
// WHITESPACE@[28; 29)
|
||||||
|
// IDENT@[29; 30) "x"
|
||||||
|
// COLON@[30; 31)
|
||||||
|
// WHITESPACE@[31; 32)
|
||||||
|
// BIND_PAT@[32; 33)
|
||||||
|
// NAME@[32; 33)
|
||||||
|
// IDENT@[32; 33) "x"
|
||||||
|
// COMMA@[33; 34)
|
||||||
|
// WHITESPACE@[34; 35)
|
||||||
|
// BIND_PAT@[35; 36)
|
||||||
|
// NAME@[35; 36)
|
||||||
|
// IDENT@[35; 36) "y"
|
||||||
|
// COMMA@[36; 37)
|
||||||
|
// WHITESPACE@[37; 38)
|
||||||
|
// DOTDOT@[38; 40)
|
||||||
|
// WHITESPACE@[40; 41)
|
||||||
|
// R_CURLY@[41; 42)
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub struct FieldPat {
|
||||||
|
pub ident: SmolStr,
|
||||||
|
pub pat: Option<TreeArc<Pat>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FieldPatList {
|
||||||
|
// TODO: try returning an iterator?
|
||||||
|
// FIXME: shouldnt the parser do this? :o
|
||||||
|
pub fn field_pats(&self) -> Vec<FieldPat> {
|
||||||
|
let mut child_iter = self.syntax().children();
|
||||||
|
let mut pats = Vec::new();
|
||||||
|
|
||||||
|
while let Some(node) = child_iter.next() {
|
||||||
|
if node.kind() != IDENT {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let ident = node.leaf_text().unwrap().clone();
|
||||||
|
let mut pat = None;
|
||||||
|
|
||||||
|
// get pat
|
||||||
|
while let Some(node) = child_iter.next() {
|
||||||
|
if node.kind() == COMMA {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(p) = Pat::cast(node) {
|
||||||
|
pat = Some(p.to_owned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let field_pat = FieldPat {
|
||||||
|
ident: ident,
|
||||||
|
pat: pat,
|
||||||
|
};
|
||||||
|
pats.push(field_pat);
|
||||||
|
}
|
||||||
|
|
||||||
|
pats
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_doc_comment_of_items() {
|
fn test_doc_comment_of_items() {
|
||||||
let file = SourceFile::parse(
|
let file = SourceFile::parse(
|
||||||
|
|
|
@ -2156,7 +2156,6 @@ pub enum PatKind<'a> {
|
||||||
PlaceholderPat(&'a PlaceholderPat),
|
PlaceholderPat(&'a PlaceholderPat),
|
||||||
PathPat(&'a PathPat),
|
PathPat(&'a PathPat),
|
||||||
StructPat(&'a StructPat),
|
StructPat(&'a StructPat),
|
||||||
FieldPatList(&'a FieldPatList),
|
|
||||||
TupleStructPat(&'a TupleStructPat),
|
TupleStructPat(&'a TupleStructPat),
|
||||||
TuplePat(&'a TuplePat),
|
TuplePat(&'a TuplePat),
|
||||||
SlicePat(&'a SlicePat),
|
SlicePat(&'a SlicePat),
|
||||||
|
@ -2171,7 +2170,6 @@ impl AstNode for Pat {
|
||||||
| PLACEHOLDER_PAT
|
| PLACEHOLDER_PAT
|
||||||
| PATH_PAT
|
| PATH_PAT
|
||||||
| STRUCT_PAT
|
| STRUCT_PAT
|
||||||
| FIELD_PAT_LIST
|
|
||||||
| TUPLE_STRUCT_PAT
|
| TUPLE_STRUCT_PAT
|
||||||
| TUPLE_PAT
|
| TUPLE_PAT
|
||||||
| SLICE_PAT
|
| SLICE_PAT
|
||||||
|
@ -2191,7 +2189,6 @@ impl Pat {
|
||||||
PLACEHOLDER_PAT => PatKind::PlaceholderPat(PlaceholderPat::cast(&self.syntax).unwrap()),
|
PLACEHOLDER_PAT => PatKind::PlaceholderPat(PlaceholderPat::cast(&self.syntax).unwrap()),
|
||||||
PATH_PAT => PatKind::PathPat(PathPat::cast(&self.syntax).unwrap()),
|
PATH_PAT => PatKind::PathPat(PathPat::cast(&self.syntax).unwrap()),
|
||||||
STRUCT_PAT => PatKind::StructPat(StructPat::cast(&self.syntax).unwrap()),
|
STRUCT_PAT => PatKind::StructPat(StructPat::cast(&self.syntax).unwrap()),
|
||||||
FIELD_PAT_LIST => PatKind::FieldPatList(FieldPatList::cast(&self.syntax).unwrap()),
|
|
||||||
TUPLE_STRUCT_PAT => PatKind::TupleStructPat(TupleStructPat::cast(&self.syntax).unwrap()),
|
TUPLE_STRUCT_PAT => PatKind::TupleStructPat(TupleStructPat::cast(&self.syntax).unwrap()),
|
||||||
TUPLE_PAT => PatKind::TuplePat(TuplePat::cast(&self.syntax).unwrap()),
|
TUPLE_PAT => PatKind::TuplePat(TuplePat::cast(&self.syntax).unwrap()),
|
||||||
SLICE_PAT => PatKind::SlicePat(SlicePat::cast(&self.syntax).unwrap()),
|
SLICE_PAT => PatKind::SlicePat(SlicePat::cast(&self.syntax).unwrap()),
|
||||||
|
@ -3066,7 +3063,15 @@ impl AstNode for StructPat {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
impl StructPat {}
|
impl StructPat {
|
||||||
|
pub fn field_pat_list(&self) -> Option<&FieldPatList> {
|
||||||
|
super::child_opt(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path(&self) -> Option<&Path> {
|
||||||
|
super::child_opt(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TokenTree
|
// TokenTree
|
||||||
#[derive(Debug, PartialEq, Eq, Hash)]
|
#[derive(Debug, PartialEq, Eq, Hash)]
|
||||||
|
|
|
@ -491,7 +491,7 @@ Grammar(
|
||||||
"BindPat": ( traits: ["NameOwner"] ),
|
"BindPat": ( traits: ["NameOwner"] ),
|
||||||
"PlaceholderPat": (),
|
"PlaceholderPat": (),
|
||||||
"PathPat": ( options: [ "Path" ] ),
|
"PathPat": ( options: [ "Path" ] ),
|
||||||
"StructPat": (),
|
"StructPat": ( options: ["FieldPatList", "Path"] ),
|
||||||
"FieldPatList": (),
|
"FieldPatList": (),
|
||||||
"TupleStructPat": (
|
"TupleStructPat": (
|
||||||
options: ["Path"],
|
options: ["Path"],
|
||||||
|
@ -508,7 +508,6 @@ Grammar(
|
||||||
"PlaceholderPat",
|
"PlaceholderPat",
|
||||||
"PathPat",
|
"PathPat",
|
||||||
"StructPat",
|
"StructPat",
|
||||||
"FieldPatList",
|
|
||||||
"TupleStructPat",
|
"TupleStructPat",
|
||||||
"TuplePat",
|
"TuplePat",
|
||||||
"SlicePat",
|
"SlicePat",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue