aboutsummaryrefslogtreecommitdiff
path: root/crates/syntax
diff options
context:
space:
mode:
Diffstat (limited to 'crates/syntax')
-rw-r--r--crates/syntax/Cargo.toml4
-rw-r--r--crates/syntax/src/algo.rs19
-rw-r--r--crates/syntax/src/ast/edit_in_place.rs153
-rw-r--r--crates/syntax/src/ast/make.rs53
-rw-r--r--crates/syntax/src/ast/node_ext.rs34
-rw-r--r--crates/syntax/src/ted.rs24
-rw-r--r--crates/syntax/src/validation/block.rs2
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast48
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rast58
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rast30
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rast96
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rs3
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_attrs.rast218
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_attrs.rs (renamed from crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs)6
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast178
17 files changed, 692 insertions, 236 deletions
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index f09cdf28a..556f80882 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,8 +13,8 @@ doctest = false
13[dependencies] 13[dependencies]
14cov-mark = { version = "1.1", features = ["thread-local"] } 14cov-mark = { version = "1.1", features = ["thread-local"] }
15itertools = "0.10.0" 15itertools = "0.10.0"
16rowan = "0.13.0-pre.3" 16rowan = "=0.13.0-pre.3"
17rustc_lexer = { version = "714.0.0", package = "rustc-ap-rustc_lexer" } 17rustc_lexer = { version = "716.0.0", package = "rustc-ap-rustc_lexer" }
18rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
19arrayvec = "0.7" 19arrayvec = "0.7"
20once_cell = "1.3.1" 20once_cell = "1.3.1"
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
index a153a9e1c..c9229c4e0 100644
--- a/crates/syntax/src/algo.rs
+++ b/crates/syntax/src/algo.rs
@@ -342,10 +342,10 @@ enum InsertPos {
342 342
343#[derive(Default)] 343#[derive(Default)]
344pub struct SyntaxRewriter<'a> { 344pub struct SyntaxRewriter<'a> {
345 f: Option<Box<dyn Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a>>,
346 //FIXME: add debug_assertions that all elements are in fact from the same file. 345 //FIXME: add debug_assertions that all elements are in fact from the same file.
347 replacements: FxHashMap<SyntaxElement, Replacement>, 346 replacements: FxHashMap<SyntaxElement, Replacement>,
348 insertions: IndexMap<InsertPos, Vec<SyntaxElement>>, 347 insertions: IndexMap<InsertPos, Vec<SyntaxElement>>,
348 _pd: std::marker::PhantomData<&'a ()>,
349} 349}
350 350
351impl fmt::Debug for SyntaxRewriter<'_> { 351impl fmt::Debug for SyntaxRewriter<'_> {
@@ -357,14 +357,7 @@ impl fmt::Debug for SyntaxRewriter<'_> {
357 } 357 }
358} 358}
359 359
360impl<'a> SyntaxRewriter<'a> { 360impl SyntaxRewriter<'_> {
361 pub fn from_fn(f: impl Fn(&SyntaxElement) -> Option<SyntaxElement> + 'a) -> SyntaxRewriter<'a> {
362 SyntaxRewriter {
363 f: Some(Box::new(f)),
364 replacements: FxHashMap::default(),
365 insertions: IndexMap::default(),
366 }
367 }
368 pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) { 361 pub fn delete<T: Clone + Into<SyntaxElement>>(&mut self, what: &T) {
369 let what = what.clone().into(); 362 let what = what.clone().into();
370 let replacement = Replacement::Delete; 363 let replacement = Replacement::Delete;
@@ -470,7 +463,7 @@ impl<'a> SyntaxRewriter<'a> {
470 pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode { 463 pub fn rewrite(&self, node: &SyntaxNode) -> SyntaxNode {
471 let _p = profile::span("rewrite"); 464 let _p = profile::span("rewrite");
472 465
473 if self.f.is_none() && self.replacements.is_empty() && self.insertions.is_empty() { 466 if self.replacements.is_empty() && self.insertions.is_empty() {
474 return node.clone(); 467 return node.clone();
475 } 468 }
476 let green = self.rewrite_children(node); 469 let green = self.rewrite_children(node);
@@ -495,7 +488,6 @@ impl<'a> SyntaxRewriter<'a> {
495 } 488 }
496 } 489 }
497 490
498 assert!(self.f.is_none());
499 self.replacements 491 self.replacements
500 .keys() 492 .keys()
501 .filter_map(element_to_node_or_parent) 493 .filter_map(element_to_node_or_parent)
@@ -510,10 +502,6 @@ impl<'a> SyntaxRewriter<'a> {
510 } 502 }
511 503
512 fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> { 504 fn replacement(&self, element: &SyntaxElement) -> Option<Replacement> {
513 if let Some(f) = &self.f {
514 assert!(self.replacements.is_empty());
515 return f(element).map(Replacement::Single);
516 }
517 self.replacements.get(element).cloned() 505 self.replacements.get(element).cloned()
518 } 506 }
519 507
@@ -574,7 +562,6 @@ fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, row
574 562
575impl ops::AddAssign for SyntaxRewriter<'_> { 563impl ops::AddAssign for SyntaxRewriter<'_> {
576 fn add_assign(&mut self, rhs: SyntaxRewriter) { 564 fn add_assign(&mut self, rhs: SyntaxRewriter) {
577 assert!(rhs.f.is_none());
578 self.replacements.extend(rhs.replacements); 565 self.replacements.extend(rhs.replacements);
579 for (pos, insertions) in rhs.insertions.into_iter() { 566 for (pos, insertions) in rhs.insertions.into_iter() {
580 match self.insertions.entry(pos) { 567 match self.insertions.entry(pos) {
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
index 529bd0eb1..04f97f368 100644
--- a/crates/syntax/src/ast/edit_in_place.rs
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -14,10 +14,29 @@ use crate::{
14use super::NameOwner; 14use super::NameOwner;
15 15
16pub trait GenericParamsOwnerEdit: ast::GenericParamsOwner + AstNodeEdit { 16pub trait GenericParamsOwnerEdit: ast::GenericParamsOwner + AstNodeEdit {
17 fn get_or_create_generic_param_list(&self) -> ast::GenericParamList;
17 fn get_or_create_where_clause(&self) -> ast::WhereClause; 18 fn get_or_create_where_clause(&self) -> ast::WhereClause;
18} 19}
19 20
20impl GenericParamsOwnerEdit for ast::Fn { 21impl GenericParamsOwnerEdit for ast::Fn {
22 fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
23 match self.generic_param_list() {
24 Some(it) => it,
25 None => {
26 let position = if let Some(name) = self.name() {
27 Position::after(name.syntax)
28 } else if let Some(fn_token) = self.fn_token() {
29 Position::after(fn_token)
30 } else if let Some(param_list) = self.param_list() {
31 Position::before(param_list.syntax)
32 } else {
33 Position::last_child_of(self.syntax())
34 };
35 create_generic_param_list(position)
36 }
37 }
38 }
39
21 fn get_or_create_where_clause(&self) -> WhereClause { 40 fn get_or_create_where_clause(&self) -> WhereClause {
22 if self.where_clause().is_none() { 41 if self.where_clause().is_none() {
23 let position = if let Some(ty) = self.ret_type() { 42 let position = if let Some(ty) = self.ret_type() {
@@ -34,6 +53,20 @@ impl GenericParamsOwnerEdit for ast::Fn {
34} 53}
35 54
36impl GenericParamsOwnerEdit for ast::Impl { 55impl GenericParamsOwnerEdit for ast::Impl {
56 fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
57 match self.generic_param_list() {
58 Some(it) => it,
59 None => {
60 let position = if let Some(imp_token) = self.impl_token() {
61 Position::after(imp_token)
62 } else {
63 Position::last_child_of(self.syntax())
64 };
65 create_generic_param_list(position)
66 }
67 }
68 }
69
37 fn get_or_create_where_clause(&self) -> WhereClause { 70 fn get_or_create_where_clause(&self) -> WhereClause {
38 if self.where_clause().is_none() { 71 if self.where_clause().is_none() {
39 let position = if let Some(items) = self.assoc_item_list() { 72 let position = if let Some(items) = self.assoc_item_list() {
@@ -48,6 +81,22 @@ impl GenericParamsOwnerEdit for ast::Impl {
48} 81}
49 82
50impl GenericParamsOwnerEdit for ast::Trait { 83impl GenericParamsOwnerEdit for ast::Trait {
84 fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
85 match self.generic_param_list() {
86 Some(it) => it,
87 None => {
88 let position = if let Some(name) = self.name() {
89 Position::after(name.syntax)
90 } else if let Some(trait_token) = self.trait_token() {
91 Position::after(trait_token)
92 } else {
93 Position::last_child_of(self.syntax())
94 };
95 create_generic_param_list(position)
96 }
97 }
98 }
99
51 fn get_or_create_where_clause(&self) -> WhereClause { 100 fn get_or_create_where_clause(&self) -> WhereClause {
52 if self.where_clause().is_none() { 101 if self.where_clause().is_none() {
53 let position = if let Some(items) = self.assoc_item_list() { 102 let position = if let Some(items) = self.assoc_item_list() {
@@ -62,6 +111,22 @@ impl GenericParamsOwnerEdit for ast::Trait {
62} 111}
63 112
64impl GenericParamsOwnerEdit for ast::Struct { 113impl GenericParamsOwnerEdit for ast::Struct {
114 fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
115 match self.generic_param_list() {
116 Some(it) => it,
117 None => {
118 let position = if let Some(name) = self.name() {
119 Position::after(name.syntax)
120 } else if let Some(struct_token) = self.struct_token() {
121 Position::after(struct_token)
122 } else {
123 Position::last_child_of(self.syntax())
124 };
125 create_generic_param_list(position)
126 }
127 }
128 }
129
65 fn get_or_create_where_clause(&self) -> WhereClause { 130 fn get_or_create_where_clause(&self) -> WhereClause {
66 if self.where_clause().is_none() { 131 if self.where_clause().is_none() {
67 let tfl = self.field_list().and_then(|fl| match fl { 132 let tfl = self.field_list().and_then(|fl| match fl {
@@ -84,6 +149,22 @@ impl GenericParamsOwnerEdit for ast::Struct {
84} 149}
85 150
86impl GenericParamsOwnerEdit for ast::Enum { 151impl GenericParamsOwnerEdit for ast::Enum {
152 fn get_or_create_generic_param_list(&self) -> ast::GenericParamList {
153 match self.generic_param_list() {
154 Some(it) => it,
155 None => {
156 let position = if let Some(name) = self.name() {
157 Position::after(name.syntax)
158 } else if let Some(enum_token) = self.enum_token() {
159 Position::after(enum_token)
160 } else {
161 Position::last_child_of(self.syntax())
162 };
163 create_generic_param_list(position)
164 }
165 }
166 }
167
87 fn get_or_create_where_clause(&self) -> WhereClause { 168 fn get_or_create_where_clause(&self) -> WhereClause {
88 if self.where_clause().is_none() { 169 if self.where_clause().is_none() {
89 let position = if let Some(gpl) = self.generic_param_list() { 170 let position = if let Some(gpl) = self.generic_param_list() {
@@ -104,6 +185,37 @@ fn create_where_clause(position: Position) {
104 ted::insert(position, where_clause.syntax()); 185 ted::insert(position, where_clause.syntax());
105} 186}
106 187
188fn create_generic_param_list(position: Position) -> ast::GenericParamList {
189 let gpl = make::generic_param_list(empty()).clone_for_update();
190 ted::insert_raw(position, gpl.syntax());
191 gpl
192}
193
194impl ast::GenericParamList {
195 pub fn add_generic_param(&self, generic_param: ast::GenericParam) {
196 match self.generic_params().last() {
197 Some(last_param) => {
198 let mut elems = Vec::new();
199 if !last_param
200 .syntax()
201 .siblings_with_tokens(Direction::Next)
202 .any(|it| it.kind() == T![,])
203 {
204 elems.push(make::token(T![,]).into());
205 elems.push(make::tokens::single_space().into());
206 };
207 elems.push(generic_param.syntax().clone().into());
208 let after_last_param = Position::after(last_param.syntax());
209 ted::insert_all(after_last_param, elems);
210 }
211 None => {
212 let after_l_angle = Position::after(self.l_angle_token().unwrap());
213 ted::insert(after_l_angle, generic_param.syntax())
214 }
215 }
216 }
217}
218
107impl ast::WhereClause { 219impl ast::WhereClause {
108 pub fn add_predicate(&self, predicate: ast::WherePred) { 220 pub fn add_predicate(&self, predicate: ast::WherePred) {
109 if let Some(pred) = self.predicates().last() { 221 if let Some(pred) = self.predicates().last() {
@@ -164,3 +276,44 @@ impl ast::Use {
164 ted::remove(self.syntax()) 276 ted::remove(self.syntax())
165 } 277 }
166} 278}
279
280#[cfg(test)]
281mod tests {
282 use std::fmt;
283
284 use crate::SourceFile;
285
286 use super::*;
287
288 fn ast_mut_from_text<N: AstNode>(text: &str) -> N {
289 let parse = SourceFile::parse(text);
290 parse.tree().syntax().descendants().find_map(N::cast).unwrap().clone_for_update()
291 }
292
293 #[test]
294 fn test_create_generic_param_list() {
295 fn check_create_gpl<N: GenericParamsOwnerEdit + fmt::Display>(before: &str, after: &str) {
296 let gpl_owner = ast_mut_from_text::<N>(before);
297 gpl_owner.get_or_create_generic_param_list();
298 assert_eq!(gpl_owner.to_string(), after);
299 }
300
301 check_create_gpl::<ast::Fn>("fn foo", "fn foo<>");
302 check_create_gpl::<ast::Fn>("fn foo() {}", "fn foo<>() {}");
303
304 check_create_gpl::<ast::Impl>("impl", "impl<>");
305 check_create_gpl::<ast::Impl>("impl Struct {}", "impl<> Struct {}");
306 check_create_gpl::<ast::Impl>("impl Trait for Struct {}", "impl<> Trait for Struct {}");
307
308 check_create_gpl::<ast::Trait>("trait Trait<>", "trait Trait<>");
309 check_create_gpl::<ast::Trait>("trait Trait<> {}", "trait Trait<> {}");
310
311 check_create_gpl::<ast::Struct>("struct A", "struct A<>");
312 check_create_gpl::<ast::Struct>("struct A;", "struct A<>;");
313 check_create_gpl::<ast::Struct>("struct A();", "struct A<>();");
314 check_create_gpl::<ast::Struct>("struct A {}", "struct A<> {}");
315
316 check_create_gpl::<ast::Enum>("enum E", "enum E<>");
317 check_create_gpl::<ast::Enum>("enum E {", "enum E<> {");
318 }
319}
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index c6a7b99b7..42da09606 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -29,9 +29,13 @@ pub fn ty(text: &str) -> ast::Type {
29pub fn ty_unit() -> ast::Type { 29pub fn ty_unit() -> ast::Type {
30 ty("()") 30 ty("()")
31} 31}
32// FIXME: handle types of length == 1
33pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type { 32pub fn ty_tuple(types: impl IntoIterator<Item = ast::Type>) -> ast::Type {
34 let contents = types.into_iter().join(", "); 33 let mut count: usize = 0;
34 let mut contents = types.into_iter().inspect(|_| count += 1).join(", ");
35 if count == 1 {
36 contents.push(',');
37 }
38
35 ty(&format!("({})", contents)) 39 ty(&format!("({})", contents))
36} 40}
37// FIXME: handle path to type 41// FIXME: handle path to type
@@ -133,6 +137,17 @@ pub fn use_(visibility: Option<ast::Visibility>, use_tree: ast::UseTree) -> ast:
133 ast_from_text(&format!("{}use {};", visibility, use_tree)) 137 ast_from_text(&format!("{}use {};", visibility, use_tree))
134} 138}
135 139
140pub fn record_expr(path: ast::Path, fields: ast::RecordExprFieldList) -> ast::RecordExpr {
141 ast_from_text(&format!("fn f() {{ {} {} }}", path, fields))
142}
143
144pub fn record_expr_field_list(
145 fields: impl IntoIterator<Item = ast::RecordExprField>,
146) -> ast::RecordExprFieldList {
147 let fields = fields.into_iter().join(", ");
148 ast_from_text(&format!("fn f() {{ S {{ {} }} }}", fields))
149}
150
136pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField { 151pub fn record_expr_field(name: ast::NameRef, expr: Option<ast::Expr>) -> ast::RecordExprField {
137 return match expr { 152 return match expr {
138 Some(expr) => from_text(&format!("{}: {}", name, expr)), 153 Some(expr) => from_text(&format!("{}: {}", name, expr)),
@@ -290,13 +305,23 @@ pub fn wildcard_pat() -> ast::WildcardPat {
290 } 305 }
291} 306}
292 307
308pub fn literal_pat(lit: &str) -> ast::LiteralPat {
309 return from_text(lit);
310
311 fn from_text(text: &str) -> ast::LiteralPat {
312 ast_from_text(&format!("fn f() {{ match x {{ {} => {{}} }} }}", text))
313 }
314}
315
293/// Creates a tuple of patterns from an iterator of patterns. 316/// Creates a tuple of patterns from an iterator of patterns.
294/// 317///
295/// Invariant: `pats` must be length > 1 318/// Invariant: `pats` must be length > 0
296///
297/// FIXME handle `pats` length == 1
298pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat { 319pub fn tuple_pat(pats: impl IntoIterator<Item = ast::Pat>) -> ast::TuplePat {
299 let pats_str = pats.into_iter().map(|p| p.to_string()).join(", "); 320 let mut count: usize = 0;
321 let mut pats_str = pats.into_iter().inspect(|_| count += 1).join(", ");
322 if count == 1 {
323 pats_str.push(',');
324 }
300 return from_text(&format!("({})", pats_str)); 325 return from_text(&format!("({})", pats_str));
301 326
302 fn from_text(text: &str) -> ast::TuplePat { 327 fn from_text(text: &str) -> ast::TuplePat {
@@ -325,6 +350,21 @@ pub fn record_pat(path: ast::Path, pats: impl IntoIterator<Item = ast::Pat>) ->
325 } 350 }
326} 351}
327 352
353pub fn record_pat_with_fields(path: ast::Path, fields: ast::RecordPatFieldList) -> ast::RecordPat {
354 ast_from_text(&format!("fn f({} {}: ()))", path, fields))
355}
356
357pub fn record_pat_field_list(
358 fields: impl IntoIterator<Item = ast::RecordPatField>,
359) -> ast::RecordPatFieldList {
360 let fields = fields.into_iter().join(", ");
361 ast_from_text(&format!("fn f(S {{ {} }}: ()))", fields))
362}
363
364pub fn record_pat_field(name_ref: ast::NameRef, pat: ast::Pat) -> ast::RecordPatField {
365 ast_from_text(&format!("fn f(S {{ {}: {} }}: ()))", name_ref, pat))
366}
367
328/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise. 368/// Returns a `BindPat` if the path has just one segment, a `PathPat` otherwise.
329pub fn path_pat(path: ast::Path) -> ast::Pat { 369pub fn path_pat(path: ast::Path) -> ast::Pat {
330 return from_text(&path.to_string()); 370 return from_text(&path.to_string());
@@ -592,6 +632,7 @@ pub mod tokens {
592 SOURCE_FILE 632 SOURCE_FILE
593 .tree() 633 .tree()
594 .syntax() 634 .syntax()
635 .clone_for_update()
595 .descendants_with_tokens() 636 .descendants_with_tokens()
596 .filter_map(|it| it.into_token()) 637 .filter_map(|it| it.into_token())
597 .find(|it| it.kind() == WHITESPACE && it.text() == "\n\n") 638 .find(|it| it.kind() == WHITESPACE && it.text() == "\n\n")
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index ae98dbd26..492fbc4a0 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -1,7 +1,7 @@
1//! Various extension methods to ast Nodes, which are hard to code-generate. 1//! Various extension methods to ast Nodes, which are hard to code-generate.
2//! Extensions for various expressions live in a sibling `expr_extensions` module. 2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3 3
4use std::fmt; 4use std::{fmt, iter::successors};
5 5
6use itertools::Itertools; 6use itertools::Itertools;
7use parser::SyntaxKind; 7use parser::SyntaxKind;
@@ -125,6 +125,18 @@ pub enum AttrKind {
125 Outer, 125 Outer,
126} 126}
127 127
128impl AttrKind {
129 /// Returns `true` if the attr_kind is [`Inner`].
130 pub fn is_inner(&self) -> bool {
131 matches!(self, Self::Inner)
132 }
133
134 /// Returns `true` if the attr_kind is [`Outer`].
135 pub fn is_outer(&self) -> bool {
136 matches!(self, Self::Outer)
137 }
138}
139
128impl ast::Attr { 140impl ast::Attr {
129 pub fn as_simple_atom(&self) -> Option<SmolStr> { 141 pub fn as_simple_atom(&self) -> Option<SmolStr> {
130 if self.eq_token().is_some() || self.token_tree().is_some() { 142 if self.eq_token().is_some() || self.token_tree().is_some() {
@@ -225,6 +237,26 @@ impl ast::Path {
225 None => self.segment(), 237 None => self.segment(),
226 } 238 }
227 } 239 }
240
241 pub fn first_qualifier_or_self(&self) -> ast::Path {
242 successors(Some(self.clone()), ast::Path::qualifier).last().unwrap()
243 }
244
245 pub fn first_segment(&self) -> Option<ast::PathSegment> {
246 self.first_qualifier_or_self().segment()
247 }
248
249 pub fn segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone {
250 // cant make use of SyntaxNode::siblings, because the returned Iterator is not clone
251 successors(self.first_segment(), |p| {
252 p.parent_path().parent_path().and_then(|p| p.segment())
253 })
254 }
255}
256impl ast::UseTree {
257 pub fn is_simple_path(&self) -> bool {
258 self.use_tree_list().is_none() && self.star_token().is_none()
259 }
228} 260}
229 261
230impl ast::UseTreeList { 262impl ast::UseTreeList {
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs
index 177d4ff67..91a06101f 100644
--- a/crates/syntax/src/ted.rs
+++ b/crates/syntax/src/ted.rs
@@ -7,7 +7,7 @@ use std::{mem, ops::RangeInclusive};
7use parser::T; 7use parser::T;
8 8
9use crate::{ 9use crate::{
10 ast::{edit::IndentLevel, make}, 10 ast::{self, edit::IndentLevel, make, AstNode},
11 SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, 11 SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
12}; 12};
13 13
@@ -147,6 +147,16 @@ pub fn append_child_raw(node: &(impl Into<SyntaxNode> + Clone), child: impl Elem
147fn ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> { 147fn ws_before(position: &Position, new: &SyntaxElement) -> Option<SyntaxToken> {
148 let prev = match &position.repr { 148 let prev = match &position.repr {
149 PositionRepr::FirstChild(_) => return None, 149 PositionRepr::FirstChild(_) => return None,
150 PositionRepr::After(it) if it.kind() == SyntaxKind::L_CURLY => {
151 if new.kind() == SyntaxKind::USE {
152 if let Some(item_list) = it.parent().and_then(ast::ItemList::cast) {
153 let mut indent = IndentLevel::from_element(&item_list.syntax().clone().into());
154 indent.0 += 1;
155 return Some(make::tokens::whitespace(&format!("\n{}", indent)));
156 }
157 }
158 it
159 }
150 PositionRepr::After(it) => it, 160 PositionRepr::After(it) => it,
151 }; 161 };
152 ws_between(prev, new) 162 ws_between(prev, new)
@@ -165,8 +175,18 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken
165 if right.kind() == T![;] || right.kind() == T![,] { 175 if right.kind() == T![;] || right.kind() == T![,] {
166 return None; 176 return None;
167 } 177 }
178 if left.kind() == T![<] || right.kind() == T![>] {
179 return None;
180 }
181 if left.kind() == T![&] && right.kind() == SyntaxKind::LIFETIME {
182 return None;
183 }
184
168 if right.kind() == SyntaxKind::USE { 185 if right.kind() == SyntaxKind::USE {
169 let indent = IndentLevel::from_element(left); 186 let mut indent = IndentLevel::from_element(left);
187 if left.kind() == SyntaxKind::USE {
188 indent.0 = IndentLevel::from_element(right).0.max(indent.0);
189 }
170 return Some(make::tokens::whitespace(&format!("\n{}", indent))); 190 return Some(make::tokens::whitespace(&format!("\n{}", indent)));
171 } 191 }
172 Some(make::tokens::single_space()) 192 Some(make::tokens::single_space())
diff --git a/crates/syntax/src/validation/block.rs b/crates/syntax/src/validation/block.rs
index ad9901468..40170014f 100644
--- a/crates/syntax/src/validation/block.rs
+++ b/crates/syntax/src/validation/block.rs
@@ -13,7 +13,7 @@ pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<Syntax
13 _ => {} 13 _ => {}
14 } 14 }
15 } 15 }
16 errors.extend(block.attrs().map(|attr| { 16 errors.extend(block.attrs().filter(|attr| attr.kind().is_inner()).map(|attr| {
17 SyntaxError::new( 17 SyntaxError::new(
18 "A block in this position cannot accept inner attributes", 18 "A block in this position cannot accept inner attributes",
19 attr.syntax().text_range(), 19 attr.syntax().text_range(),
diff --git a/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast
index 3016a6574..1ff3f7656 100644
--- a/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0117_macro_call_type.rast
@@ -7,15 +7,16 @@ [email protected]
7 [email protected] " " 7 [email protected] " "
8 [email protected] "=" 8 [email protected] "="
9 [email protected] " " 9 [email protected] " "
10 [email protected] 10 [email protected]
11 [email protected] 11 [email protected]
12 [email protected] 12 [email protected]
13 [email protected] 13 [email protected]
14 [email protected] "foo" 14 [email protected]
15 [email protected] "!" 15 [email protected] "foo"
16 [email protected] 16 [email protected] "!"
17 [email protected] "(" 17 [email protected]
18 [email protected] ")" 18 [email protected] "("
19 [email protected] ")"
19 [email protected] ";" 20 [email protected] ";"
20 [email protected] "\n" 21 [email protected] "\n"
21 [email protected] 22 [email protected]
@@ -26,19 +27,20 @@ [email protected]
26 [email protected] " " 27 [email protected] " "
27 [email protected] "=" 28 [email protected] "="
28 [email protected] " " 29 [email protected] " "
29 [email protected] 30 [email protected]
30 [email protected] 31 [email protected]
31 [email protected] 32 [email protected]
32 [email protected] 33 [email protected]
33 [email protected] 34 [email protected]
34 [email protected] "crate" 35 [email protected]
35 [email protected] "::" 36 [email protected] "crate"
36 [email protected] 37 [email protected] "::"
37 [email protected] 38 [email protected]
38 [email protected] "foo" 39 [email protected]
39 [email protected] "!" 40 [email protected] "foo"
40 [email protected] 41 [email protected] "!"
41 [email protected] "(" 42 [email protected]
42 [email protected] ")" 43 [email protected] "("
44 [email protected] ")"
43 [email protected] ";" 45 [email protected] ";"
44 [email protected] "\n" 46 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rast b/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rast
index 925409bdf..e9202a612 100644
--- a/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rast
@@ -1,5 +1,5 @@
1SOURCE_FILE@0..63 1SOURCE_FILE@0..102
2 FN@0..62 2 FN@0..101
3 [email protected] "fn" 3 [email protected] "fn"
4 [email protected] " " 4 [email protected] " "
5 [email protected] 5 [email protected]
@@ -8,7 +8,7 @@ [email protected]
8 [email protected] "(" 8 [email protected] "("
9 [email protected] ")" 9 [email protected] ")"
10 [email protected] " " 10 [email protected] " "
11 BLOCK_EXPR@9..62 11 BLOCK_EXPR@9..101
12 [email protected] "{" 12 [email protected] "{"
13 [email protected] "\n " 13 [email protected] "\n "
14 [email protected] 14 [email protected]
@@ -70,6 +70,52 @@ [email protected]
70 [email protected] "(" 70 [email protected] "("
71 [email protected] ")" 71 [email protected] ")"
72 [email protected] ";" 72 [email protected] ";"
73 [email protected] "\n" 73 [email protected] "\n "
74 [email protected] "}" 74 [email protected]
75 [email protected] "\n" 75 [email protected] "let"
76 [email protected] " "
77 [email protected]
78 [email protected]
79 [email protected]
80 [email protected]
81 [email protected] "S"
82 [email protected] " "
83 [email protected]
84 [email protected] "{"
85 [email protected] " "
86 [email protected]
87 [email protected]
88 [email protected] "#"
89 [email protected] "["
90 [email protected]
91 [email protected]
92 [email protected]
93 [email protected] "cfg"
94 [email protected]
95 [email protected] "("
96 [email protected] "any"
97 [email protected]
98 [email protected] "("
99 [email protected] ")"
100 [email protected] ")"
101 [email protected] "]"
102 [email protected] " "
103 [email protected]
104 [email protected] "x"
105 [email protected] ":"
106 [email protected] " "
107 [email protected]
108 [email protected]
109 [email protected] "1"
110 [email protected] " "
111 [email protected] "}"
112 [email protected] " "
113 [email protected] "="
114 [email protected] " "
115 [email protected]
116 [email protected] "("
117 [email protected] ")"
118 [email protected] ";"
119 [email protected] "\n"
120 [email protected] "}"
121 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rs b/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rs
index 26b1d5f89..53cfdc22d 100644
--- a/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rs
+++ b/crates/syntax/test_data/parser/inline/ok/0145_record_pat_field.rs
@@ -1,4 +1,5 @@
1fn foo() { 1fn foo() {
2 let S { 0: 1 } = (); 2 let S { 0: 1 } = ();
3 let S { x: 1 } = (); 3 let S { x: 1 } = ();
4 let S { #[cfg(any())] x: 1 } = ();
4} 5}
diff --git a/crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rast b/crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rast
new file mode 100644
index 000000000..b20e523dc
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rast
@@ -0,0 +1,30 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "f"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] " "
14 [email protected]
15 [email protected]
16 [email protected]
17 [email protected]
18 [email protected] "S"
19 [email protected]
20 [email protected] "::"
21 [email protected] "<"
22 [email protected]
23 [email protected]
24 [email protected] "-"
25 [email protected]
26 [email protected] "1"
27 [email protected] ">"
28 [email protected] " "
29 [email protected] "}"
30 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rs b/crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rs
new file mode 100644
index 000000000..8a81d05cd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0164_const_generic_negated_literal.rs
@@ -0,0 +1 @@
fn f() { S::<-1> }
diff --git a/crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rast b/crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rast
new file mode 100644
index 000000000..e8f40a4cd
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rast
@@ -0,0 +1,96 @@
1[email protected]
2 [email protected]
3 [email protected] "struct"
4 [email protected] " "
5 [email protected]
6 [email protected] "A"
7 [email protected]
8 [email protected] "<"
9 [email protected]
10 [email protected] "const"
11 [email protected] " "
12 [email protected]
13 [email protected] "N"
14 [email protected] ":"
15 [email protected] " "
16 [email protected]
17 [email protected]
18 [email protected]
19 [email protected]
20 [email protected] "i32"
21 [email protected] " "
22 [email protected] "="
23 [email protected] " "
24 [email protected]
25 [email protected]
26 [email protected] "-"
27 [email protected]
28 [email protected] "1"
29 [email protected] ">"
30 [email protected] ";"
31 [email protected] "\n"
32 [email protected]
33 [email protected] "struct"
34 [email protected] " "
35 [email protected]
36 [email protected] "B"
37 [email protected]
38 [email protected] "<"
39 [email protected]
40 [email protected] "const"
41 [email protected] " "
42 [email protected]
43 [email protected] "N"
44 [email protected] ":"
45 [email protected] " "
46 [email protected]
47 [email protected]
48 [email protected]
49 [email protected]
50 [email protected] "i32"
51 [email protected] " "
52 [email protected] "="
53 [email protected] " "
54 [email protected]
55 [email protected]
56 [email protected] "{"
57 [email protected] "}"
58 [email protected] ">"
59 [email protected] ";"
60 [email protected] "\n"
61 [email protected]
62 [email protected] "struct"
63 [email protected] " "
64 [email protected]
65 [email protected] "C"
66 [email protected]
67 [email protected] "<"
68 [email protected]
69 [email protected] "const"
70 [email protected] " "
71 [email protected]
72 [email protected] "N"
73 [email protected] ":"
74 [email protected] " "
75 [email protected]
76 [email protected]
77 [email protected]
78 [email protected]
79 [email protected] "i32"
80 [email protected] " "
81 [email protected] "="
82 [email protected] " "
83 [email protected]
84 [email protected]
85 [email protected]
86 [email protected]
87 [email protected]
88 [email protected]
89 [email protected] "some"
90 [email protected] "::"
91 [email protected]
92 [email protected]
93 [email protected] "CONST"
94 [email protected] ">"
95 [email protected] ";"
96 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rs b/crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rs
new file mode 100644
index 000000000..68388c8fb
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0165_const_param_defaults.rs
@@ -0,0 +1,3 @@
1struct A<const N: i32 = -1>;
2struct B<const N: i32 = {}>;
3struct C<const N: i32 = some::CONST>;
diff --git a/crates/syntax/test_data/parser/ok/0045_block_attrs.rast b/crates/syntax/test_data/parser/ok/0045_block_attrs.rast
new file mode 100644
index 000000000..50ab52d32
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0045_block_attrs.rast
@@ -0,0 +1,218 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "inner"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] "\n "
14 [email protected]
15 [email protected] "#"
16 [email protected] "!"
17 [email protected] "["
18 [email protected]
19 [email protected]
20 [email protected]
21 [email protected] "doc"
22 [email protected]
23 [email protected] "("
24 [email protected] "\"Inner attributes all ..."
25 [email protected] ")"
26 [email protected] "]"
27 [email protected] "\n "
28 [email protected] "//! As are ModuleDoc ..."
29 [email protected] "\n "
30 [email protected]
31 [email protected]
32 [email protected] "{"
33 [email protected] "\n "
34 [email protected]
35 [email protected] "#"
36 [email protected] "!"
37 [email protected] "["
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected] "doc"
42 [email protected]
43 [email protected] "("
44 [email protected] "\"Inner attributes are ..."
45 [email protected] ")"
46 [email protected] "]"
47 [email protected] "\n "
48 [email protected]
49 [email protected] "#"
50 [email protected] "!"
51 [email protected] "["
52 [email protected]
53 [email protected]
54 [email protected]
55 [email protected] "doc"
56 [email protected]
57 [email protected] "("
58 [email protected] "\"Being validated is n ..."
59 [email protected] ")"
60 [email protected] "]"
61 [email protected] "\n "
62 [email protected] "//! As are ModuleDoc ..."
63 [email protected] "\n "
64 [email protected] "}"
65 [email protected] ";"
66 [email protected] "\n "
67 [email protected]
68 [email protected] "{"
69 [email protected] "\n "
70 [email protected]
71 [email protected] "#"
72 [email protected] "!"
73 [email protected] "["
74 [email protected]
75 [email protected]
76 [email protected]
77 [email protected] "doc"
78 [email protected]
79 [email protected] "("
80 [email protected] "\"Inner attributes are ..."
81 [email protected] ")"
82 [email protected] "]"
83 [email protected] "\n "
84 [email protected] "//! As are ModuleDoc ..."
85 [email protected] "\n "
86 [email protected] "}"
87 [email protected] "\n"
88 [email protected] "}"
89 [email protected] "\n\n"
90 [email protected]
91 [email protected] "fn"
92 [email protected] " "
93 [email protected]
94 [email protected] "outer"
95 [email protected]
96 [email protected] "("
97 [email protected] ")"
98 [email protected] " "
99 [email protected]
100 [email protected] "{"
101 [email protected] "\n "
102 [email protected]
103 [email protected] "let"
104 [email protected] " "
105 [email protected]
106 [email protected] "_"
107 [email protected] " "
108 [email protected] "="
109 [email protected] " "
110 [email protected]
111 [email protected]
112 [email protected] "#"
113 [email protected] "["
114 [email protected]
115 [email protected]
116 [email protected]
117 [email protected] "doc"
118 [email protected]
119 [email protected] "("
120 [email protected] "\"Outer attributes are ..."
121 [email protected] ")"
122 [email protected] "]"
123 [email protected] " "
124 [email protected] "{"
125 [email protected] "}"
126 [email protected] ";"
127 [email protected] "\n"
128 [email protected] "}"
129 [email protected] "\n\n"
130 [email protected] "// https://github.com ..."
131 [email protected] "\n"
132 [email protected]
133 [email protected] "impl"
134 [email protected] " "
135 [email protected]
136 [email protected]
137 [email protected]
138 [email protected]
139 [email protected] "Whatever"
140 [email protected] " "
141 [email protected]
142 [email protected] "{"
143 [email protected] "\n "
144 [email protected]
145 [email protected] "fn"
146 [email protected] " "
147 [email protected]
148 [email protected] "salsa_event"
149 [email protected]
150 [email protected] "("
151 [email protected]
152 [email protected] "&"
153 [email protected]
154 [email protected] "self"
155 [email protected] ","
156 [email protected] " "
157 [email protected]
158 [email protected]
159 [email protected]
160 [email protected] "event_fn"
161 [email protected] ":"
162 [email protected] " "
163 [email protected]
164 [email protected] "impl"
165 [email protected] " "
166 [email protected]
167 [email protected]
168 [email protected]
169 [email protected]
170 [email protected]
171 [email protected]
172 [email protected] "Fn"
173 [email protected]
174 [email protected] "("
175 [email protected] ")"
176 [email protected] " "
177 [email protected]
178 [email protected] "->"
179 [email protected] " "
180 [email protected]
181 [email protected]
182 [email protected]
183 [email protected]
184 [email protected] "Event"
185 [email protected]
186 [email protected] "<"
187 [email protected]
188 [email protected]
189 [email protected]
190 [email protected]
191 [email protected]
192 [email protected] "Self"
193 [email protected] ">"
194 [email protected] ")"
195 [email protected] " "
196 [email protected]
197 [email protected] "{"
198 [email protected] "\n "
199 [email protected]
200 [email protected] "#"
201 [email protected] "!"
202 [email protected] "["
203 [email protected]
204 [email protected]
205 [email protected]
206 [email protected] "allow"
207 [email protected]
208 [email protected] "("
209 [email protected] "unused_variables"
210 [email protected] ")"
211 [email protected] "]"
212 [email protected] " "
213 [email protected] "// this is `inner_at ..."
214 [email protected] "\n "
215 [email protected] "}"
216 [email protected] "\n"
217 [email protected] "}"
218 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs b/crates/syntax/test_data/parser/ok/0045_block_attrs.rs
index 88df8138e..ed4593759 100644
--- a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs
+++ b/crates/syntax/test_data/parser/ok/0045_block_attrs.rs
@@ -1,4 +1,4 @@
1fn block() { 1fn inner() {
2 #![doc("Inner attributes allowed here")] 2 #![doc("Inner attributes allowed here")]
3 //! As are ModuleDoc style comments 3 //! As are ModuleDoc style comments
4 { 4 {
@@ -12,6 +12,10 @@ fn block() {
12 } 12 }
13} 13}
14 14
15fn outer() {
16 let _ = #[doc("Outer attributes are always allowed")] {};
17}
18
15// https://github.com/rust-analyzer/rust-analyzer/issues/689 19// https://github.com/rust-analyzer/rust-analyzer/issues/689
16impl Whatever { 20impl Whatever {
17 fn salsa_event(&self, event_fn: impl Fn() -> Event<Self>) { 21 fn salsa_event(&self, event_fn: impl Fn() -> Event<Self>) {
diff --git a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
deleted file mode 100644
index 6afed5f05..000000000
--- a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
+++ /dev/null
@@ -1,178 +0,0 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "block"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] "\n "
14 [email protected]
15 [email protected] "#"
16 [email protected] "!"
17 [email protected] "["
18 [email protected]
19 [email protected]
20 [email protected]
21 [email protected] "doc"
22 [email protected]
23 [email protected] "("
24 [email protected] "\"Inner attributes all ..."
25 [email protected] ")"
26 [email protected] "]"
27 [email protected] "\n "
28 [email protected] "//! As are ModuleDoc ..."
29 [email protected] "\n "
30 [email protected]
31 [email protected]
32 [email protected] "{"
33 [email protected] "\n "
34 [email protected]
35 [email protected] "#"
36 [email protected] "!"
37 [email protected] "["
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected] "doc"
42 [email protected]
43 [email protected] "("
44 [email protected] "\"Inner attributes are ..."
45 [email protected] ")"
46 [email protected] "]"
47 [email protected] "\n "
48 [email protected]
49 [email protected] "#"
50 [email protected] "!"
51 [email protected] "["
52 [email protected]
53 [email protected]
54 [email protected]
55 [email protected] "doc"
56 [email protected]
57 [email protected] "("
58 [email protected] "\"Being validated is n ..."
59 [email protected] ")"
60 [email protected] "]"
61 [email protected] "\n "
62 [email protected] "//! As are ModuleDoc ..."
63 [email protected] "\n "
64 [email protected] "}"
65 [email protected] ";"
66 [email protected] "\n "
67 [email protected]
68 [email protected] "{"
69 [email protected] "\n "
70 [email protected]
71 [email protected] "#"
72 [email protected] "!"
73 [email protected] "["
74 [email protected]
75 [email protected]
76 [email protected]
77 [email protected] "doc"
78 [email protected]
79 [email protected] "("
80 [email protected] "\"Inner attributes are ..."
81 [email protected] ")"
82 [email protected] "]"
83 [email protected] "\n "
84 [email protected] "//! As are ModuleDoc ..."
85 [email protected] "\n "
86 [email protected] "}"
87 [email protected] "\n"
88 [email protected] "}"
89 [email protected] "\n\n"
90 [email protected] "// https://github.com ..."
91 [email protected] "\n"
92 [email protected]
93 [email protected] "impl"
94 [email protected] " "
95 [email protected]
96 [email protected]
97 [email protected]
98 [email protected]
99 [email protected] "Whatever"
100 [email protected] " "
101 [email protected]
102 [email protected] "{"
103 [email protected] "\n "
104 [email protected]
105 [email protected] "fn"
106 [email protected] " "
107 [email protected]
108 [email protected] "salsa_event"
109 [email protected]
110 [email protected] "("
111 [email protected]
112 [email protected] "&"
113 [email protected]
114 [email protected] "self"
115 [email protected] ","
116 [email protected] " "
117 [email protected]
118 [email protected]
119 [email protected]
120 [email protected] "event_fn"
121 [email protected] ":"
122 [email protected] " "
123 [email protected]
124 [email protected] "impl"
125 [email protected] " "
126 [email protected]
127 [email protected]
128 [email protected]
129 [email protected]
130 [email protected]
131 [email protected]
132 [email protected] "Fn"
133 [email protected]
134 [email protected] "("
135 [email protected] ")"
136 [email protected] " "
137 [email protected]
138 [email protected] "->"
139 [email protected] " "
140 [email protected]
141 [email protected]
142 [email protected]
143 [email protected]
144 [email protected] "Event"
145 [email protected]
146 [email protected] "<"
147 [email protected]
148 [email protected]
149 [email protected]
150 [email protected]
151 [email protected]
152 [email protected] "Self"
153 [email protected] ">"
154 [email protected] ")"
155 [email protected] " "
156 [email protected]
157 [email protected] "{"
158 [email protected] "\n "
159 [email protected]
160 [email protected] "#"
161 [email protected] "!"
162 [email protected] "["
163 [email protected]
164 [email protected]
165 [email protected]
166 [email protected] "allow"
167 [email protected]
168 [email protected] "("
169 [email protected] "unused_variables"
170 [email protected] ")"
171 [email protected] "]"
172 [email protected] " "
173 [email protected] "// this is `inner_at ..."
174 [email protected] "\n "
175 [email protected] "}"
176 [email protected] "\n"
177 [email protected] "}"
178 [email protected] "\n"