aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2018-08-26 10:09:28 +0100
committerAleksey Kladov <[email protected]>2018-08-26 10:09:28 +0100
commitac226021cfd26a9332b5971f3e05118d77822af5 (patch)
tree04e9d19956b74d551f798bf26f420fa978b8f30f /crates
parent4c121bfa2f2a7a06f01143e3203c650156e2fb4e (diff)
scope based comletion
Diffstat (limited to 'crates')
-rw-r--r--crates/libeditor/src/code_actions.rs2
-rw-r--r--crates/libeditor/src/completion.rs42
-rw-r--r--crates/libeditor/tests/test.rs34
-rw-r--r--crates/libsyntax2/src/algo/visit.rs58
-rw-r--r--crates/libsyntax2/src/algo/walk.rs10
-rw-r--r--crates/libsyntax2/src/ast/generated.rs308
-rw-r--r--crates/libsyntax2/src/grammar.ron58
-rw-r--r--crates/libsyntax2/src/grammar/items/mod.rs4
8 files changed, 475 insertions, 41 deletions
diff --git a/crates/libeditor/src/code_actions.rs b/crates/libeditor/src/code_actions.rs
index f53a8f9c6..e6ba83d2e 100644
--- a/crates/libeditor/src/code_actions.rs
+++ b/crates/libeditor/src/code_actions.rs
@@ -9,7 +9,7 @@ use libsyntax2::{
9 SyntaxNodeRef, 9 SyntaxNodeRef,
10 algo::{ 10 algo::{
11 Direction, siblings, 11 Direction, siblings,
12 find_leaf_at_offset, ancestors, 12 find_leaf_at_offset,
13 }, 13 },
14}; 14};
15 15
diff --git a/crates/libeditor/src/completion.rs b/crates/libeditor/src/completion.rs
index cf61ec784..16c9ead74 100644
--- a/crates/libeditor/src/completion.rs
+++ b/crates/libeditor/src/completion.rs
@@ -1,7 +1,11 @@
1use libsyntax2::{ 1use libsyntax2::{
2 File, TextUnit, 2 File, TextUnit, AstNode, SyntaxNodeRef,
3 ast, 3 ast::{self, NameOwner},
4 algo::find_leaf_at_offset, 4 algo::{
5 ancestors,
6 visit::{visitor_ctx, VisitorCtx},
7 walk::preorder,
8 },
5}; 9};
6 10
7use { 11use {
@@ -25,7 +29,33 @@ pub fn scope_completion(file: &File, offset: TextUnit) -> Option<Vec<CompletionI
25} 29}
26 30
27fn complete(name_ref: ast::NameRef) -> Vec<CompletionItem> { 31fn complete(name_ref: ast::NameRef) -> Vec<CompletionItem> {
28 vec![CompletionItem { 32 let mut res = Vec::new();
29 name: "foo".to_string() 33 for node in ancestors(name_ref.syntax()) {
30 }] 34 process_scope(node, &mut res);
35 }
36 res
37}
38
39fn process_scope(node: SyntaxNodeRef, sink: &mut Vec<CompletionItem>) {
40 let _ = visitor_ctx(sink)
41 .visit::<ast::Block, _>(|block, sink| {
42 block.let_stmts()
43 .filter_map(|it| it.pat())
44 .for_each(move |it| process_pat(it, sink))
45 })
46 .visit::<ast::FnDef, _>(|fn_def, sink| {
47 fn_def.param_list().into_iter()
48 .flat_map(|it| it.params())
49 .filter_map(|it| it.pat())
50 .for_each(move |it| process_pat(it, sink))
51 })
52 .accept(node);
53
54 fn process_pat(pat: ast::Pat, sink: &mut Vec<CompletionItem>) {
55 let items = preorder(pat.syntax())
56 .filter_map(ast::BindPat::cast)
57 .filter_map(ast::BindPat::name)
58 .map(|name| CompletionItem { name: name.text().to_string() });
59 sink.extend(items);
60 }
31} 61}
diff --git a/crates/libeditor/tests/test.rs b/crates/libeditor/tests/test.rs
index 20de2f240..ecdc149c7 100644
--- a/crates/libeditor/tests/test.rs
+++ b/crates/libeditor/tests/test.rs
@@ -256,25 +256,23 @@ struct Foo { f: u32 }
256"); 256");
257} 257}
258 258
259// #[test] 259#[test]
260// fn test_completion() { 260fn test_completion() {
261// fn do_check(code: &str, expected_completions: &str) { 261 fn do_check(code: &str, expected_completions: &str) {
262// let (off, code) = extract_offset(&code); 262 let (off, code) = extract_offset(&code);
263// let file = file(&code); 263 let file = file(&code);
264// let completions = scope_completion(&file, off).unwrap(); 264 let completions = scope_completion(&file, off).unwrap();
265// assert_eq_dbg(expected_completions, &completions); 265 assert_eq_dbg(expected_completions, &completions);
266// } 266 }
267 267
268// do_check(r" 268 do_check(r"
269// fn foo(foo: i32) { 269fn quux(x: i32) {
270// let bar = 92; 270 let y = 92;
271// 1 + <|> 271 1 + <|>
272// } 272}
273// ", r#" 273", r#"[CompletionItem { name: "y" },
274// CompletionItem { name: "bar" }, 274 CompletionItem { name: "x" }]"#);
275// CompletionItem { name: "foo" }, 275}
276// "#);
277// }
278 276
279fn file(text: &str) -> File { 277fn file(text: &str) -> File {
280 File::parse(text) 278 File::parse(text)
diff --git a/crates/libsyntax2/src/algo/visit.rs b/crates/libsyntax2/src/algo/visit.rs
index a36c8f45e..9f1c127c7 100644
--- a/crates/libsyntax2/src/algo/visit.rs
+++ b/crates/libsyntax2/src/algo/visit.rs
@@ -6,6 +6,10 @@ pub fn visitor<'a, T>() -> impl Visitor<'a, Output=T> {
6 EmptyVisitor { ph: PhantomData } 6 EmptyVisitor { ph: PhantomData }
7} 7}
8 8
9pub fn visitor_ctx<'a, T, C>(ctx: C) -> impl VisitorCtx<'a, Output=T, Ctx=C> {
10 EmptyVisitorCtx { ph: PhantomData, ctx }
11}
12
9pub trait Visitor<'a>: Sized { 13pub trait Visitor<'a>: Sized {
10 type Output; 14 type Output;
11 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>; 15 fn accept(self, node: SyntaxNodeRef<'a>) -> Option<Self::Output>;
@@ -17,6 +21,18 @@ pub trait Visitor<'a>: Sized {
17 } 21 }
18} 22}
19 23
24pub trait VisitorCtx<'a>: Sized {
25 type Output;
26 type Ctx;
27 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx>;
28 fn visit<N, F>(self, f: F) -> VisCtx<Self, N, F>
29 where N: AstNode<'a>,
30 F: FnOnce(N, Self::Ctx) -> Self::Output,
31 {
32 VisCtx { inner: self, f, ph: PhantomData }
33 }
34}
35
20#[derive(Debug)] 36#[derive(Debug)]
21struct EmptyVisitor<T> { 37struct EmptyVisitor<T> {
22 ph: PhantomData<fn() -> T> 38 ph: PhantomData<fn() -> T>
@@ -31,6 +47,21 @@ impl<'a, T> Visitor<'a> for EmptyVisitor<T> {
31} 47}
32 48
33#[derive(Debug)] 49#[derive(Debug)]
50struct EmptyVisitorCtx<T, C> {
51 ctx: C,
52 ph: PhantomData<fn() -> T>,
53}
54
55impl<'a, T, C> VisitorCtx<'a> for EmptyVisitorCtx<T, C> {
56 type Output = T;
57 type Ctx = C;
58
59 fn accept(self, _node: SyntaxNodeRef<'a>) -> Result<T, C> {
60 Err(self.ctx)
61 }
62}
63
64#[derive(Debug)]
34pub struct Vis<V, N, F> { 65pub struct Vis<V, N, F> {
35 inner: V, 66 inner: V,
36 f: F, 67 f: F,
@@ -50,3 +81,30 @@ impl<'a, V, N, F> Visitor<'a> for Vis<V, N, F>
50 inner.accept(node).or_else(|| N::cast(node).map(f)) 81 inner.accept(node).or_else(|| N::cast(node).map(f))
51 } 82 }
52} 83}
84
85#[derive(Debug)]
86pub struct VisCtx<V, N, F> {
87 inner: V,
88 f: F,
89 ph: PhantomData<fn(N)>,
90}
91
92impl<'a, V, N, F> VisitorCtx<'a> for VisCtx<V, N, F>
93 where
94 V: VisitorCtx<'a>,
95 N: AstNode<'a>,
96 F: FnOnce(N, <V as VisitorCtx<'a>>::Ctx) -> <V as VisitorCtx<'a>>::Output,
97{
98 type Output = <V as VisitorCtx<'a>>::Output;
99 type Ctx = <V as VisitorCtx<'a>>::Ctx;
100
101 fn accept(self, node: SyntaxNodeRef<'a>) -> Result<Self::Output, Self::Ctx> {
102 let VisCtx { inner, f, .. } = self;
103 inner.accept(node).or_else(|ctx|
104 match N::cast(node) {
105 None => Err(ctx),
106 Some(node) => Ok(f(node, ctx))
107 }
108 )
109 }
110}
diff --git a/crates/libsyntax2/src/algo/walk.rs b/crates/libsyntax2/src/algo/walk.rs
index d8797c453..536ee705f 100644
--- a/crates/libsyntax2/src/algo/walk.rs
+++ b/crates/libsyntax2/src/algo/walk.rs
@@ -17,19 +17,19 @@ pub enum WalkEvent<'a> {
17} 17}
18 18
19pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> { 19pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> {
20 generate(Some(WalkEvent::Enter(root)), |pos| { 20 generate(Some(WalkEvent::Enter(root)), move |pos| {
21 let next = match *pos { 21 let next = match *pos {
22 WalkEvent::Enter(node) => match node.first_child() { 22 WalkEvent::Enter(node) => match node.first_child() {
23 Some(child) => WalkEvent::Enter(child), 23 Some(child) => WalkEvent::Enter(child),
24 None => WalkEvent::Exit(node), 24 None => WalkEvent::Exit(node),
25 }, 25 },
26 WalkEvent::Exit(node) => { 26 WalkEvent::Exit(node) => {
27 if node == root {
28 return None;
29 }
27 match node.next_sibling() { 30 match node.next_sibling() {
28 Some(sibling) => WalkEvent::Enter(sibling), 31 Some(sibling) => WalkEvent::Enter(sibling),
29 None => match node.parent() { 32 None => WalkEvent::Exit(node.parent().unwrap()),
30 Some(node) => WalkEvent::Exit(node),
31 None => return None,
32 },
33 } 33 }
34 } 34 }
35 }; 35 };
diff --git a/crates/libsyntax2/src/ast/generated.rs b/crates/libsyntax2/src/ast/generated.rs
index 7d746a85b..6926c0535 100644
--- a/crates/libsyntax2/src/ast/generated.rs
+++ b/crates/libsyntax2/src/ast/generated.rs
@@ -80,6 +80,25 @@ impl<'a> AstNode<'a> for BinExpr<'a> {
80 80
81impl<'a> BinExpr<'a> {} 81impl<'a> BinExpr<'a> {}
82 82
83// BindPat
84#[derive(Debug, Clone, Copy)]
85pub struct BindPat<'a> {
86 syntax: SyntaxNodeRef<'a>,
87}
88
89impl<'a> AstNode<'a> for BindPat<'a> {
90 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
91 match syntax.kind() {
92 BIND_PAT => Some(BindPat { syntax }),
93 _ => None,
94 }
95 }
96 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
97}
98
99impl<'a> ast::NameOwner<'a> for BindPat<'a> {}
100impl<'a> BindPat<'a> {}
101
83// Block 102// Block
84#[derive(Debug, Clone, Copy)] 103#[derive(Debug, Clone, Copy)]
85pub struct Block<'a> { 104pub struct Block<'a> {
@@ -96,7 +115,11 @@ impl<'a> AstNode<'a> for Block<'a> {
96 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax } 115 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
97} 116}
98 117
99impl<'a> Block<'a> {} 118impl<'a> Block<'a> {
119 pub fn let_stmts(self) -> impl Iterator<Item = LetStmt<'a>> + 'a {
120 super::children(self)
121 }
122}
100 123
101// BlockExpr 124// BlockExpr
102#[derive(Debug, Clone, Copy)] 125#[derive(Debug, Clone, Copy)]
@@ -378,6 +401,24 @@ impl<'a> AstNode<'a> for FieldExpr<'a> {
378 401
379impl<'a> FieldExpr<'a> {} 402impl<'a> FieldExpr<'a> {}
380 403
404// FieldPatList
405#[derive(Debug, Clone, Copy)]
406pub struct FieldPatList<'a> {
407 syntax: SyntaxNodeRef<'a>,
408}
409
410impl<'a> AstNode<'a> for FieldPatList<'a> {
411 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
412 match syntax.kind() {
413 FIELD_PAT_LIST => Some(FieldPatList { syntax }),
414 _ => None,
415 }
416 }
417 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
418}
419
420impl<'a> FieldPatList<'a> {}
421
381// FnDef 422// FnDef
382#[derive(Debug, Clone, Copy)] 423#[derive(Debug, Clone, Copy)]
383pub struct FnDef<'a> { 424pub struct FnDef<'a> {
@@ -397,7 +438,11 @@ impl<'a> AstNode<'a> for FnDef<'a> {
397impl<'a> ast::NameOwner<'a> for FnDef<'a> {} 438impl<'a> ast::NameOwner<'a> for FnDef<'a> {}
398impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {} 439impl<'a> ast::TypeParamsOwner<'a> for FnDef<'a> {}
399impl<'a> ast::AttrsOwner<'a> for FnDef<'a> {} 440impl<'a> ast::AttrsOwner<'a> for FnDef<'a> {}
400impl<'a> FnDef<'a> {} 441impl<'a> FnDef<'a> {
442 pub fn param_list(self) -> Option<ParamList<'a>> {
443 super::child_opt(self)
444 }
445}
401 446
402// FnPointerType 447// FnPointerType
403#[derive(Debug, Clone, Copy)] 448#[derive(Debug, Clone, Copy)]
@@ -561,6 +606,28 @@ impl<'a> AstNode<'a> for LambdaExpr<'a> {
561 606
562impl<'a> LambdaExpr<'a> {} 607impl<'a> LambdaExpr<'a> {}
563 608
609// LetStmt
610#[derive(Debug, Clone, Copy)]
611pub struct LetStmt<'a> {
612 syntax: SyntaxNodeRef<'a>,
613}
614
615impl<'a> AstNode<'a> for LetStmt<'a> {
616 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
617 match syntax.kind() {
618 LET_STMT => Some(LetStmt { syntax }),
619 _ => None,
620 }
621 }
622 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
623}
624
625impl<'a> LetStmt<'a> {
626 pub fn pat(self) -> Option<Pat<'a>> {
627 super::child_opt(self)
628 }
629}
630
564// LoopExpr 631// LoopExpr
565#[derive(Debug, Clone, Copy)] 632#[derive(Debug, Clone, Copy)]
566pub struct LoopExpr<'a> { 633pub struct LoopExpr<'a> {
@@ -831,6 +898,50 @@ impl<'a> ast::TypeParamsOwner<'a> for NominalDef<'a> {}
831impl<'a> ast::AttrsOwner<'a> for NominalDef<'a> {} 898impl<'a> ast::AttrsOwner<'a> for NominalDef<'a> {}
832impl<'a> NominalDef<'a> {} 899impl<'a> NominalDef<'a> {}
833 900
901// Param
902#[derive(Debug, Clone, Copy)]
903pub struct Param<'a> {
904 syntax: SyntaxNodeRef<'a>,
905}
906
907impl<'a> AstNode<'a> for Param<'a> {
908 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
909 match syntax.kind() {
910 PARAM => Some(Param { syntax }),
911 _ => None,
912 }
913 }
914 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
915}
916
917impl<'a> Param<'a> {
918 pub fn pat(self) -> Option<Pat<'a>> {
919 super::child_opt(self)
920 }
921}
922
923// ParamList
924#[derive(Debug, Clone, Copy)]
925pub struct ParamList<'a> {
926 syntax: SyntaxNodeRef<'a>,
927}
928
929impl<'a> AstNode<'a> for ParamList<'a> {
930 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
931 match syntax.kind() {
932 PARAM_LIST => Some(ParamList { syntax }),
933 _ => None,
934 }
935 }
936 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
937}
938
939impl<'a> ParamList<'a> {
940 pub fn params(self) -> impl Iterator<Item = Param<'a>> + 'a {
941 super::children(self)
942 }
943}
944
834// ParenExpr 945// ParenExpr
835#[derive(Debug, Clone, Copy)] 946#[derive(Debug, Clone, Copy)]
836pub struct ParenExpr<'a> { 947pub struct ParenExpr<'a> {
@@ -867,6 +978,55 @@ impl<'a> AstNode<'a> for ParenType<'a> {
867 978
868impl<'a> ParenType<'a> {} 979impl<'a> ParenType<'a> {}
869 980
981// Pat
982#[derive(Debug, Clone, Copy)]
983pub enum Pat<'a> {
984 RefPat(RefPat<'a>),
985 BindPat(BindPat<'a>),
986 PlaceholderPat(PlaceholderPat<'a>),
987 PathPat(PathPat<'a>),
988 StructPat(StructPat<'a>),
989 FieldPatList(FieldPatList<'a>),
990 TupleStructPat(TupleStructPat<'a>),
991 TuplePat(TuplePat<'a>),
992 SlicePat(SlicePat<'a>),
993 RangePat(RangePat<'a>),
994}
995
996impl<'a> AstNode<'a> for Pat<'a> {
997 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
998 match syntax.kind() {
999 REF_PAT => Some(Pat::RefPat(RefPat { syntax })),
1000 BIND_PAT => Some(Pat::BindPat(BindPat { syntax })),
1001 PLACEHOLDER_PAT => Some(Pat::PlaceholderPat(PlaceholderPat { syntax })),
1002 PATH_PAT => Some(Pat::PathPat(PathPat { syntax })),
1003 STRUCT_PAT => Some(Pat::StructPat(StructPat { syntax })),
1004 FIELD_PAT_LIST => Some(Pat::FieldPatList(FieldPatList { syntax })),
1005 TUPLE_STRUCT_PAT => Some(Pat::TupleStructPat(TupleStructPat { syntax })),
1006 TUPLE_PAT => Some(Pat::TuplePat(TuplePat { syntax })),
1007 SLICE_PAT => Some(Pat::SlicePat(SlicePat { syntax })),
1008 RANGE_PAT => Some(Pat::RangePat(RangePat { syntax })),
1009 _ => None,
1010 }
1011 }
1012 fn syntax(self) -> SyntaxNodeRef<'a> {
1013 match self {
1014 Pat::RefPat(inner) => inner.syntax(),
1015 Pat::BindPat(inner) => inner.syntax(),
1016 Pat::PlaceholderPat(inner) => inner.syntax(),
1017 Pat::PathPat(inner) => inner.syntax(),
1018 Pat::StructPat(inner) => inner.syntax(),
1019 Pat::FieldPatList(inner) => inner.syntax(),
1020 Pat::TupleStructPat(inner) => inner.syntax(),
1021 Pat::TuplePat(inner) => inner.syntax(),
1022 Pat::SlicePat(inner) => inner.syntax(),
1023 Pat::RangePat(inner) => inner.syntax(),
1024 }
1025 }
1026}
1027
1028impl<'a> Pat<'a> {}
1029
870// PathExpr 1030// PathExpr
871#[derive(Debug, Clone, Copy)] 1031#[derive(Debug, Clone, Copy)]
872pub struct PathExpr<'a> { 1032pub struct PathExpr<'a> {
@@ -885,6 +1045,24 @@ impl<'a> AstNode<'a> for PathExpr<'a> {
885 1045
886impl<'a> PathExpr<'a> {} 1046impl<'a> PathExpr<'a> {}
887 1047
1048// PathPat
1049#[derive(Debug, Clone, Copy)]
1050pub struct PathPat<'a> {
1051 syntax: SyntaxNodeRef<'a>,
1052}
1053
1054impl<'a> AstNode<'a> for PathPat<'a> {
1055 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1056 match syntax.kind() {
1057 PATH_PAT => Some(PathPat { syntax }),
1058 _ => None,
1059 }
1060 }
1061 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1062}
1063
1064impl<'a> PathPat<'a> {}
1065
888// PathType 1066// PathType
889#[derive(Debug, Clone, Copy)] 1067#[derive(Debug, Clone, Copy)]
890pub struct PathType<'a> { 1068pub struct PathType<'a> {
@@ -903,6 +1081,24 @@ impl<'a> AstNode<'a> for PathType<'a> {
903 1081
904impl<'a> PathType<'a> {} 1082impl<'a> PathType<'a> {}
905 1083
1084// PlaceholderPat
1085#[derive(Debug, Clone, Copy)]
1086pub struct PlaceholderPat<'a> {
1087 syntax: SyntaxNodeRef<'a>,
1088}
1089
1090impl<'a> AstNode<'a> for PlaceholderPat<'a> {
1091 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1092 match syntax.kind() {
1093 PLACEHOLDER_PAT => Some(PlaceholderPat { syntax }),
1094 _ => None,
1095 }
1096 }
1097 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1098}
1099
1100impl<'a> PlaceholderPat<'a> {}
1101
906// PlaceholderType 1102// PlaceholderType
907#[derive(Debug, Clone, Copy)] 1103#[derive(Debug, Clone, Copy)]
908pub struct PlaceholderType<'a> { 1104pub struct PlaceholderType<'a> {
@@ -975,6 +1171,24 @@ impl<'a> AstNode<'a> for RangeExpr<'a> {
975 1171
976impl<'a> RangeExpr<'a> {} 1172impl<'a> RangeExpr<'a> {}
977 1173
1174// RangePat
1175#[derive(Debug, Clone, Copy)]
1176pub struct RangePat<'a> {
1177 syntax: SyntaxNodeRef<'a>,
1178}
1179
1180impl<'a> AstNode<'a> for RangePat<'a> {
1181 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1182 match syntax.kind() {
1183 RANGE_PAT => Some(RangePat { syntax }),
1184 _ => None,
1185 }
1186 }
1187 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1188}
1189
1190impl<'a> RangePat<'a> {}
1191
978// RefExpr 1192// RefExpr
979#[derive(Debug, Clone, Copy)] 1193#[derive(Debug, Clone, Copy)]
980pub struct RefExpr<'a> { 1194pub struct RefExpr<'a> {
@@ -993,6 +1207,24 @@ impl<'a> AstNode<'a> for RefExpr<'a> {
993 1207
994impl<'a> RefExpr<'a> {} 1208impl<'a> RefExpr<'a> {}
995 1209
1210// RefPat
1211#[derive(Debug, Clone, Copy)]
1212pub struct RefPat<'a> {
1213 syntax: SyntaxNodeRef<'a>,
1214}
1215
1216impl<'a> AstNode<'a> for RefPat<'a> {
1217 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1218 match syntax.kind() {
1219 REF_PAT => Some(RefPat { syntax }),
1220 _ => None,
1221 }
1222 }
1223 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1224}
1225
1226impl<'a> RefPat<'a> {}
1227
996// ReferenceType 1228// ReferenceType
997#[derive(Debug, Clone, Copy)] 1229#[derive(Debug, Clone, Copy)]
998pub struct ReferenceType<'a> { 1230pub struct ReferenceType<'a> {
@@ -1055,6 +1287,24 @@ impl<'a> Root<'a> {
1055 } 1287 }
1056} 1288}
1057 1289
1290// SlicePat
1291#[derive(Debug, Clone, Copy)]
1292pub struct SlicePat<'a> {
1293 syntax: SyntaxNodeRef<'a>,
1294}
1295
1296impl<'a> AstNode<'a> for SlicePat<'a> {
1297 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1298 match syntax.kind() {
1299 SLICE_PAT => Some(SlicePat { syntax }),
1300 _ => None,
1301 }
1302 }
1303 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1304}
1305
1306impl<'a> SlicePat<'a> {}
1307
1058// SliceType 1308// SliceType
1059#[derive(Debug, Clone, Copy)] 1309#[derive(Debug, Clone, Copy)]
1060pub struct SliceType<'a> { 1310pub struct SliceType<'a> {
@@ -1137,6 +1387,24 @@ impl<'a> AstNode<'a> for StructLit<'a> {
1137 1387
1138impl<'a> StructLit<'a> {} 1388impl<'a> StructLit<'a> {}
1139 1389
1390// StructPat
1391#[derive(Debug, Clone, Copy)]
1392pub struct StructPat<'a> {
1393 syntax: SyntaxNodeRef<'a>,
1394}
1395
1396impl<'a> AstNode<'a> for StructPat<'a> {
1397 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1398 match syntax.kind() {
1399 STRUCT_PAT => Some(StructPat { syntax }),
1400 _ => None,
1401 }
1402 }
1403 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1404}
1405
1406impl<'a> StructPat<'a> {}
1407
1140// TokenTree 1408// TokenTree
1141#[derive(Debug, Clone, Copy)] 1409#[derive(Debug, Clone, Copy)]
1142pub struct TokenTree<'a> { 1410pub struct TokenTree<'a> {
@@ -1211,6 +1479,42 @@ impl<'a> AstNode<'a> for TupleExpr<'a> {
1211 1479
1212impl<'a> TupleExpr<'a> {} 1480impl<'a> TupleExpr<'a> {}
1213 1481
1482// TuplePat
1483#[derive(Debug, Clone, Copy)]
1484pub struct TuplePat<'a> {
1485 syntax: SyntaxNodeRef<'a>,
1486}
1487
1488impl<'a> AstNode<'a> for TuplePat<'a> {
1489 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1490 match syntax.kind() {
1491 TUPLE_PAT => Some(TuplePat { syntax }),
1492 _ => None,
1493 }
1494 }
1495 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1496}
1497
1498impl<'a> TuplePat<'a> {}
1499
1500// TupleStructPat
1501#[derive(Debug, Clone, Copy)]
1502pub struct TupleStructPat<'a> {
1503 syntax: SyntaxNodeRef<'a>,
1504}
1505
1506impl<'a> AstNode<'a> for TupleStructPat<'a> {
1507 fn cast(syntax: SyntaxNodeRef<'a>) -> Option<Self> {
1508 match syntax.kind() {
1509 TUPLE_STRUCT_PAT => Some(TupleStructPat { syntax }),
1510 _ => None,
1511 }
1512 }
1513 fn syntax(self) -> SyntaxNodeRef<'a> { self.syntax }
1514}
1515
1516impl<'a> TupleStructPat<'a> {}
1517
1214// TupleType 1518// TupleType
1215#[derive(Debug, Clone, Copy)] 1519#[derive(Debug, Clone, Copy)]
1216pub struct TupleType<'a> { 1520pub struct TupleType<'a> {
diff --git a/crates/libsyntax2/src/grammar.ron b/crates/libsyntax2/src/grammar.ron
index a753d5e48..3a125ace6 100644
--- a/crates/libsyntax2/src/grammar.ron
+++ b/crates/libsyntax2/src/grammar.ron
@@ -241,11 +241,16 @@ Grammar(
241 ["modules", "Module"], 241 ["modules", "Module"],
242 ] 242 ]
243 ), 243 ),
244 "FnDef": ( traits: [ 244 "FnDef": (
245 "NameOwner", 245 traits: [
246 "TypeParamsOwner", 246 "NameOwner",
247 "AttrsOwner", 247 "TypeParamsOwner",
248 ] ), 248 "AttrsOwner",
249 ],
250 options: [
251 ["param_list", "ParamList"]
252 ],
253 ),
249 "StructDef": ( 254 "StructDef": (
250 traits: [ 255 traits: [
251 "NameOwner", 256 "NameOwner",
@@ -393,13 +398,52 @@ Grammar(
393 ], 398 ],
394 ), 399 ),
395 400
401 "RefPat": (),
402 "BindPat": ( traits: ["NameOwner"] ),
403 "PlaceholderPat": (),
404 "PathPat": (),
405 "StructPat": (),
406 "FieldPatList": (),
407 "TupleStructPat": (),
408 "TuplePat": (),
409 "SlicePat": (),
410 "RangePat": (),
411
412 "Pat": (
413 enum: [
414 "RefPat",
415 "BindPat",
416 "PlaceholderPat",
417 "PathPat",
418 "StructPat",
419 "FieldPatList",
420 "TupleStructPat",
421 "TuplePat",
422 "SlicePat",
423 "RangePat",
424 ],
425 ),
426
396 "Name": (), 427 "Name": (),
397 "NameRef": (), 428 "NameRef": (),
398 "Attr": ( options: [ ["value", "TokenTree"] ] ), 429 "Attr": ( options: [ ["value", "TokenTree"] ] ),
399 "TokenTree": (), 430 "TokenTree": (),
400 "TypeParamList": ( collections: [ ["type_params", "TypeParam" ] ]), 431 "TypeParamList": ( collections: [ ["type_params", "TypeParam" ] ]),
401 "TypeParam": ( traits: ["NameOwner"]), 432 "TypeParam": ( traits: ["NameOwner"] ),
402 "WhereClause": (), 433 "WhereClause": (),
403 "Block": (), 434 "LetStmt": ( options: [ ["pat", "Pat"] ]),
435 "Block": (
436 collections: [
437 ["let_stmts", "LetStmt"],
438 ]
439 ),
440 "ParamList": (
441 collections: [
442 ["params", "Param"]
443 ]
444 ),
445 "Param": (
446 options: [["pat", "Pat"]],
447 )
404 }, 448 },
405) 449)
diff --git a/crates/libsyntax2/src/grammar/items/mod.rs b/crates/libsyntax2/src/grammar/items/mod.rs
index a285892df..7c6f7b63e 100644
--- a/crates/libsyntax2/src/grammar/items/mod.rs
+++ b/crates/libsyntax2/src/grammar/items/mod.rs
@@ -115,7 +115,7 @@ pub(super) fn maybe_item(p: &mut Parser, flavor: ItemFlavor) -> MaybeItem {
115 // test unsafe_fn 115 // test unsafe_fn
116 // unsafe fn foo() {} 116 // unsafe fn foo() {}
117 FN_KW => { 117 FN_KW => {
118 function(p, flavor); 118 fn_def(p, flavor);
119 FN_DEF 119 FN_DEF
120 } 120 }
121 121
@@ -227,7 +227,7 @@ fn extern_item_list(p: &mut Parser) {
227 m.complete(p, EXTERN_ITEM_LIST); 227 m.complete(p, EXTERN_ITEM_LIST);
228} 228}
229 229
230fn function(p: &mut Parser, flavor: ItemFlavor) { 230fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
231 assert!(p.at(FN_KW)); 231 assert!(p.at(FN_KW));
232 p.bump(); 232 p.bump();
233 233