aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/handlers/add_impl.rs4
-rw-r--r--crates/ra_assists/src/handlers/add_new.rs5
-rw-r--r--crates/ra_assists/src/handlers/introduce_variable.rs4
-rw-r--r--crates/ra_assists/src/handlers/merge_imports.rs4
-rw-r--r--crates/ra_fmt/src/lib.rs6
-rw-r--r--crates/ra_hir_def/src/body/lower.rs10
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs4
-rw-r--r--crates/ra_hir_def/src/path/lower.rs2
-rw-r--r--crates/ra_hir_def/src/path/lower/lower_use.rs2
-rw-r--r--crates/ra_hir_def/src/visibility.rs4
-rw-r--r--crates/ra_hir_ty/src/tests.rs4
-rw-r--r--crates/ra_parser/src/syntax_kind/generated.rs6
-rw-r--r--crates/ra_syntax/src/ast.rs2
-rw-r--r--crates/ra_syntax/src/ast/edit.rs26
-rw-r--r--crates/ra_syntax/src/ast/expr_extensions.rs4
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs148
-rw-r--r--crates/ra_syntax/src/ast/traits.rs32
17 files changed, 144 insertions, 123 deletions
diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs
index 6622eadb2..72a201b6d 100644
--- a/crates/ra_assists/src/handlers/add_impl.rs
+++ b/crates/ra_assists/src/handlers/add_impl.rs
@@ -1,5 +1,5 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, AstNode, NameOwner, TypeParamsOwner}, 2 ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner},
3 TextUnit, 3 TextUnit,
4}; 4};
5use stdx::{format_to, SepBy}; 5use stdx::{format_to, SepBy};
@@ -42,7 +42,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option<Assist> {
42 if let Some(type_params) = type_params { 42 if let Some(type_params) = type_params {
43 let lifetime_params = type_params 43 let lifetime_params = type_params
44 .lifetime_params() 44 .lifetime_params()
45 .filter_map(|it| it.lifetime_token()) 45 .filter_map(|it| it.lifetime())
46 .map(|it| it.text().clone()); 46 .map(|it| it.text().clone());
47 let type_params = 47 let type_params =
48 type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); 48 type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs
index 240b19fa3..c10397249 100644
--- a/crates/ra_assists/src/handlers/add_new.rs
+++ b/crates/ra_assists/src/handlers/add_new.rs
@@ -1,7 +1,8 @@
1use hir::Adt; 1use hir::Adt;
2use ra_syntax::{ 2use ra_syntax::{
3 ast::{ 3 ast::{
4 self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, 4 self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner,
5 VisibilityOwner,
5 }, 6 },
6 TextUnit, T, 7 TextUnit, T,
7}; 8};
@@ -105,7 +106,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String {
105 if let Some(type_params) = type_params { 106 if let Some(type_params) = type_params {
106 let lifetime_params = type_params 107 let lifetime_params = type_params
107 .lifetime_params() 108 .lifetime_params()
108 .filter_map(|it| it.lifetime_token()) 109 .filter_map(|it| it.lifetime())
109 .map(|it| it.text().clone()); 110 .map(|it| it.text().clone());
110 let type_params = 111 let type_params =
111 type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); 112 type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs
index 1edbdc14c..9963f884b 100644
--- a/crates/ra_assists/src/handlers/introduce_variable.rs
+++ b/crates/ra_assists/src/handlers/introduce_variable.rs
@@ -1,5 +1,5 @@
1use ra_syntax::{ 1use ra_syntax::{
2 ast::{self, AstNode}, 2 ast::{self, AstElement, AstNode},
3 SyntaxKind::{ 3 SyntaxKind::{
4 BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR, 4 BLOCK_EXPR, BREAK_EXPR, COMMENT, LAMBDA_EXPR, LOOP_EXPR, MATCH_ARM, PATH_EXPR, RETURN_EXPR,
5 WHITESPACE, 5 WHITESPACE,
@@ -124,7 +124,7 @@ fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
124 } 124 }
125 } 125 }
126 126
127 if ast::Stmt::cast(node.clone()).is_some() { 127 if ast::Stmt::cast_element(node.clone().into()).is_some() {
128 return Some((node, false)); 128 return Some((node, false));
129 } 129 }
130 130
diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs
index 5d4b74e56..f8b3ddb4e 100644
--- a/crates/ra_assists/src/handlers/merge_imports.rs
+++ b/crates/ra_assists/src/handlers/merge_imports.rs
@@ -3,7 +3,7 @@ use std::iter::successors;
3use ra_syntax::{ 3use ra_syntax::{
4 algo::{neighbor, SyntaxRewriter}, 4 algo::{neighbor, SyntaxRewriter},
5 ast::{self, edit::AstNodeEdit, make}, 5 ast::{self, edit::AstNodeEdit, make},
6 AstNode, Direction, InsertPosition, SyntaxElement, T, 6 AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T,
7}; 7};
8 8
9use crate::{Assist, AssistCtx, AssistId}; 9use crate::{Assist, AssistCtx, AssistId};
@@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option<ast::UseTre
82 .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']), 82 .filter(|it| it.kind() != T!['{'] && it.kind() != T!['}']),
83 ); 83 );
84 let use_tree_list = lhs.use_tree_list()?; 84 let use_tree_list = lhs.use_tree_list()?;
85 let pos = InsertPosition::Before(use_tree_list.r_curly()?.into()); 85 let pos = InsertPosition::Before(use_tree_list.r_curly()?.syntax().clone().into());
86 let use_tree_list = use_tree_list.insert_children(pos, to_insert); 86 let use_tree_list = use_tree_list.insert_children(pos, to_insert);
87 Some(lhs.with_use_tree_list(use_tree_list)) 87 Some(lhs.with_use_tree_list(use_tree_list))
88} 88}
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index db27f9b83..0b4ba1bbe 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -60,10 +60,10 @@ pub fn extract_trivial_expression(block: &ast::BlockExpr) -> Option<ast::Expr> {
60 } else { 60 } else {
61 // Unwrap `{ continue; }` 61 // Unwrap `{ continue; }`
62 let (stmt,) = block.statements().next_tuple()?; 62 let (stmt,) = block.statements().next_tuple()?;
63 if has_anything_else(stmt.syntax()) {
64 return None;
65 }
66 if let ast::Stmt::ExprStmt(expr_stmt) = stmt { 63 if let ast::Stmt::ExprStmt(expr_stmt) = stmt {
64 if has_anything_else(expr_stmt.syntax()) {
65 return None;
66 }
67 let expr = expr_stmt.expr()?; 67 let expr = expr_stmt.expr()?;
68 match expr.syntax().kind() { 68 match expr.syntax().kind() {
69 CONTINUE_EXPR | BREAK_EXPR | RETURN_EXPR => return Some(expr), 69 CONTINUE_EXPR | BREAK_EXPR | RETURN_EXPR => return Some(expr),
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 8d4b8b0f0..8338414fa 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -482,14 +482,17 @@ impl ExprCollector<'_> {
482 self.collect_block_items(&block); 482 self.collect_block_items(&block);
483 let statements = block 483 let statements = block
484 .statements() 484 .statements()
485 .map(|s| match s { 485 .filter_map(|s| match s {
486 ast::Stmt::LetStmt(stmt) => { 486 ast::Stmt::LetStmt(stmt) => {
487 let pat = self.collect_pat_opt(stmt.pat()); 487 let pat = self.collect_pat_opt(stmt.pat());
488 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); 488 let type_ref = stmt.ascribed_type().map(TypeRef::from_ast);
489 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 489 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
490 Statement::Let { pat, type_ref, initializer } 490 Some(Statement::Let { pat, type_ref, initializer })
491 } 491 }
492 ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())), 492 ast::Stmt::ExprStmt(stmt) => {
493 Some(Statement::Expr(self.collect_expr_opt(stmt.expr())))
494 }
495 ast::Stmt::ModuleItem(_) => None,
493 }) 496 })
494 .collect(); 497 .collect();
495 let tail = block.expr().map(|e| self.collect_expr(e)); 498 let tail = block.expr().map(|e| self.collect_expr(e));
@@ -541,6 +544,7 @@ impl ExprCollector<'_> {
541 let ast_id = self.expander.ast_id(&def); 544 let ast_id = self.expander.ast_id(&def);
542 (TraitLoc { container, ast_id }.intern(self.db).into(), def.name()) 545 (TraitLoc { container, ast_id }.intern(self.db).into(), def.name())
543 } 546 }
547 ast::ModuleItem::ExternBlock(_) => continue, // FIXME: collect from extern blocks
544 ast::ModuleItem::ImplDef(_) 548 ast::ModuleItem::ImplDef(_)
545 | ast::ModuleItem::UseItem(_) 549 | ast::ModuleItem::UseItem(_)
546 | ast::ModuleItem::ExternCrateItem(_) 550 | ast::ModuleItem::ExternCrateItem(_)
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index 8f190e7f9..a9dff3a5d 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -266,6 +266,10 @@ impl RawItemsCollector {
266 self.add_macro(current_module, it); 266 self.add_macro(current_module, it);
267 return; 267 return;
268 } 268 }
269 ast::ModuleItem::ExternBlock(_) => {
270 // FIXME: add extern block
271 return;
272 }
269 }; 273 };
270 if let Some(name) = name { 274 if let Some(name) = name {
271 let name = name.as_name(); 275 let name = name.as_name();
diff --git a/crates/ra_hir_def/src/path/lower.rs b/crates/ra_hir_def/src/path/lower.rs
index 4900000fe..3c13cb2c7 100644
--- a/crates/ra_hir_def/src/path/lower.rs
+++ b/crates/ra_hir_def/src/path/lower.rs
@@ -28,7 +28,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
28 loop { 28 loop {
29 let segment = path.segment()?; 29 let segment = path.segment()?;
30 30
31 if segment.has_colon_colon() { 31 if segment.coloncolon().is_some() {
32 kind = PathKind::Abs; 32 kind = PathKind::Abs;
33 } 33 }
34 34
diff --git a/crates/ra_hir_def/src/path/lower/lower_use.rs b/crates/ra_hir_def/src/path/lower/lower_use.rs
index 278d5196e..6ec944228 100644
--- a/crates/ra_hir_def/src/path/lower/lower_use.rs
+++ b/crates/ra_hir_def/src/path/lower/lower_use.rs
@@ -34,7 +34,7 @@ pub(crate) fn lower_use_tree(
34 let alias = tree.alias().map(|a| { 34 let alias = tree.alias().map(|a| {
35 a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias) 35 a.name().map(|it| it.as_name()).map_or(ImportAlias::Underscore, ImportAlias::Alias)
36 }); 36 });
37 let is_glob = tree.has_star(); 37 let is_glob = tree.star().is_some();
38 if let Some(ast_path) = tree.path() { 38 if let Some(ast_path) = tree.path() {
39 // Handle self in a path. 39 // Handle self in a path.
40 // E.g. `use something::{self, <...>}` 40 // E.g. `use something::{self, <...>}`
diff --git a/crates/ra_hir_def/src/visibility.rs b/crates/ra_hir_def/src/visibility.rs
index 62513873e..1482d3be0 100644
--- a/crates/ra_hir_def/src/visibility.rs
+++ b/crates/ra_hir_def/src/visibility.rs
@@ -84,6 +84,10 @@ impl RawVisibility {
84 let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() }; 84 let path = ModPath { kind: PathKind::Super(1), segments: Vec::new() };
85 RawVisibility::Module(path) 85 RawVisibility::Module(path)
86 } 86 }
87 ast::VisibilityKind::PubSelf => {
88 let path = ModPath { kind: PathKind::Plain, segments: Vec::new() };
89 RawVisibility::Module(path)
90 }
87 ast::VisibilityKind::Pub => RawVisibility::Public, 91 ast::VisibilityKind::Pub => RawVisibility::Public,
88 } 92 }
89 } 93 }
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 608408d88..ac0966236 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -23,7 +23,7 @@ use insta::assert_snapshot;
23use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; 23use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
24use ra_syntax::{ 24use ra_syntax::{
25 algo, 25 algo,
26 ast::{self, AstNode}, 26 ast::{self, AstNode, AstToken},
27}; 27};
28use stdx::format_to; 28use stdx::format_to;
29 29
@@ -101,7 +101,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
101 let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db)); 101 let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db));
102 102
103 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { 103 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
104 (self_param.self_kw_token().text_range(), "self".to_string()) 104 (self_param.self_kw().unwrap().syntax().text_range(), "self".to_string())
105 } else { 105 } else {
106 (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) 106 (src_ptr.value.range(), node.text().to_string().replace("\n", " "))
107 }; 107 };
diff --git a/crates/ra_parser/src/syntax_kind/generated.rs b/crates/ra_parser/src/syntax_kind/generated.rs
index 4c16cf1cd..004f4e564 100644
--- a/crates/ra_parser/src/syntax_kind/generated.rs
+++ b/crates/ra_parser/src/syntax_kind/generated.rs
@@ -105,6 +105,7 @@ pub enum SyntaxKind {
105 DEFAULT_KW, 105 DEFAULT_KW,
106 EXISTENTIAL_KW, 106 EXISTENTIAL_KW,
107 UNION_KW, 107 UNION_KW,
108 RAW_KW,
108 INT_NUMBER, 109 INT_NUMBER,
109 FLOAT_NUMBER, 110 FLOAT_NUMBER,
110 CHAR, 111 CHAR,
@@ -258,7 +259,7 @@ impl SyntaxKind {
258 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW 259 | IMPL_KW | IN_KW | LET_KW | LOOP_KW | MACRO_KW | MATCH_KW | MOD_KW | MOVE_KW
259 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW 260 | MUT_KW | PUB_KW | REF_KW | RETURN_KW | SELF_KW | STATIC_KW | STRUCT_KW | SUPER_KW
260 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW 261 | TRAIT_KW | TRUE_KW | TRY_KW | TYPE_KW | UNSAFE_KW | USE_KW | WHERE_KW | WHILE_KW
261 | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW => true, 262 | AUTO_KW | DEFAULT_KW | EXISTENTIAL_KW | UNION_KW | RAW_KW => true,
262 _ => false, 263 _ => false,
263 } 264 }
264 } 265 }
@@ -651,4 +652,7 @@ macro_rules! T {
651 ( union ) => { 652 ( union ) => {
652 $crate::SyntaxKind::UNION_KW 653 $crate::SyntaxKind::UNION_KW
653 }; 654 };
655 ( raw ) => {
656 $crate::SyntaxKind::RAW_KW
657 };
654} 658}
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index ab0f44dd2..c81b68d3e 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -271,7 +271,7 @@ where
271 let pred = predicates.next().unwrap(); 271 let pred = predicates.next().unwrap();
272 let mut bounds = pred.type_bound_list().unwrap().bounds(); 272 let mut bounds = pred.type_bound_list().unwrap().bounds();
273 273
274 assert_eq!("'a", pred.lifetime_token().unwrap().text()); 274 assert_eq!("'a", pred.lifetime().unwrap().text());
275 275
276 assert_bound("'b", bounds.next()); 276 assert_bound("'b", bounds.next());
277 assert_bound("'c", bounds.next()); 277 assert_bound("'c", bounds.next());
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs
index b69cae234..d79310995 100644
--- a/crates/ra_syntax/src/ast/edit.rs
+++ b/crates/ra_syntax/src/ast/edit.rs
@@ -99,7 +99,7 @@ impl ast::ItemList {
99 None => match self.l_curly() { 99 None => match self.l_curly() {
100 Some(it) => ( 100 Some(it) => (
101 " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(), 101 " ".to_string() + &leading_indent(self.syntax()).unwrap_or_default(),
102 InsertPosition::After(it), 102 InsertPosition::After(it.syntax().clone().into()),
103 ), 103 ),
104 None => return self.clone(), 104 None => return self.clone(),
105 }, 105 },
@@ -109,10 +109,6 @@ impl ast::ItemList {
109 [ws.ws().into(), item.syntax().clone().into()].into(); 109 [ws.ws().into(), item.syntax().clone().into()].into();
110 self.insert_children(position, to_insert) 110 self.insert_children(position, to_insert)
111 } 111 }
112
113 fn l_curly(&self) -> Option<SyntaxElement> {
114 self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
115 }
116} 112}
117 113
118impl ast::RecordFieldList { 114impl ast::RecordFieldList {
@@ -147,7 +143,7 @@ impl ast::RecordFieldList {
147 macro_rules! after_l_curly { 143 macro_rules! after_l_curly {
148 () => {{ 144 () => {{
149 let anchor = match self.l_curly() { 145 let anchor = match self.l_curly() {
150 Some(it) => it, 146 Some(it) => it.syntax().clone().into(),
151 None => return self.clone(), 147 None => return self.clone(),
152 }; 148 };
153 InsertPosition::After(anchor) 149 InsertPosition::After(anchor)
@@ -189,24 +185,20 @@ impl ast::RecordFieldList {
189 185
190 self.insert_children(position, to_insert) 186 self.insert_children(position, to_insert)
191 } 187 }
192
193 fn l_curly(&self) -> Option<SyntaxElement> {
194 self.syntax().children_with_tokens().find(|it| it.kind() == T!['{'])
195 }
196} 188}
197 189
198impl ast::TypeParam { 190impl ast::TypeParam {
199 #[must_use] 191 #[must_use]
200 pub fn remove_bounds(&self) -> ast::TypeParam { 192 pub fn remove_bounds(&self) -> ast::TypeParam {
201 let colon = match self.colon_token() { 193 let colon = match self.colon() {
202 Some(it) => it, 194 Some(it) => it,
203 None => return self.clone(), 195 None => return self.clone(),
204 }; 196 };
205 let end = match self.type_bound_list() { 197 let end = match self.type_bound_list() {
206 Some(it) => it.syntax().clone().into(), 198 Some(it) => it.syntax().clone().into(),
207 None => colon.clone().into(), 199 None => colon.syntax().clone().into(),
208 }; 200 };
209 self.replace_children(colon.into()..=end, iter::empty()) 201 self.replace_children(colon.syntax().clone().into()..=end, iter::empty())
210 } 202 }
211} 203}
212 204
@@ -305,8 +297,12 @@ impl ast::UseTree {
305 Some(it) => it, 297 Some(it) => it,
306 None => return self.clone(), 298 None => return self.clone(),
307 }; 299 };
308 let use_tree = 300 let use_tree = make::use_tree(
309 make::use_tree(suffix.clone(), self.use_tree_list(), self.alias(), self.has_star()); 301 suffix.clone(),
302 self.use_tree_list(),
303 self.alias(),
304 self.star().is_some(),
305 );
310 let nested = make::use_tree_list(iter::once(use_tree)); 306 let nested = make::use_tree_list(iter::once(use_tree));
311 return make::use_tree(prefix.clone(), Some(nested), None, false); 307 return make::use_tree(prefix.clone(), Some(nested), None, false);
312 308
diff --git a/crates/ra_syntax/src/ast/expr_extensions.rs b/crates/ra_syntax/src/ast/expr_extensions.rs
index 8bbd946c0..40c8fca3b 100644
--- a/crates/ra_syntax/src/ast/expr_extensions.rs
+++ b/crates/ra_syntax/src/ast/expr_extensions.rs
@@ -52,6 +52,10 @@ impl ast::RefExpr {
52 pub fn is_mut(&self) -> bool { 52 pub fn is_mut(&self) -> bool {
53 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut]) 53 self.syntax().children_with_tokens().any(|n| n.kind() == T![mut])
54 } 54 }
55
56 pub fn raw_token(&self) -> Option<SyntaxToken> {
57 None // FIXME: implement &raw
58 }
55} 59}
56 60
57#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] 61#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index bf7d137be..400eba210 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -4,7 +4,10 @@
4use itertools::Itertools; 4use itertools::Itertools;
5 5
6use crate::{ 6use crate::{
7 ast::{self, child_opt, children, AstNode, AttrInput, NameOwner, SyntaxNode}, 7 ast::{
8 self, child_opt, child_token_opt, children, AstElement, AstNode, AstToken, AttrInput,
9 NameOwner, SyntaxNode,
10 },
8 SmolStr, SyntaxElement, 11 SmolStr, SyntaxElement,
9 SyntaxKind::*, 12 SyntaxKind::*,
10 SyntaxToken, T, 13 SyntaxToken, T,
@@ -130,13 +133,6 @@ impl ast::PathSegment {
130 }; 133 };
131 Some(res) 134 Some(res)
132 } 135 }
133
134 pub fn has_colon_colon(&self) -> bool {
135 match self.syntax.first_child_or_token().map(|s| s.kind()) {
136 Some(T![::]) => true,
137 _ => false,
138 }
139 }
140} 136}
141 137
142impl ast::Path { 138impl ast::Path {
@@ -154,12 +150,6 @@ impl ast::Module {
154 } 150 }
155} 151}
156 152
157impl ast::UseTree {
158 pub fn has_star(&self) -> bool {
159 self.syntax().children_with_tokens().any(|it| it.kind() == T![*])
160 }
161}
162
163impl ast::UseTreeList { 153impl ast::UseTreeList {
164 pub fn parent_use_tree(&self) -> ast::UseTree { 154 pub fn parent_use_tree(&self) -> ast::UseTree {
165 self.syntax() 155 self.syntax()
@@ -167,20 +157,6 @@ impl ast::UseTreeList {
167 .and_then(ast::UseTree::cast) 157 .and_then(ast::UseTree::cast)
168 .expect("UseTreeLists are always nested in UseTrees") 158 .expect("UseTreeLists are always nested in UseTrees")
169 } 159 }
170 pub fn l_curly(&self) -> Option<SyntaxToken> {
171 self.token(T!['{'])
172 }
173
174 pub fn r_curly(&self) -> Option<SyntaxToken> {
175 self.token(T!['}'])
176 }
177
178 fn token(&self, kind: SyntaxKind) -> Option<SyntaxToken> {
179 self.syntax()
180 .children_with_tokens()
181 .filter_map(|it| it.into_token())
182 .find(|it| it.kind() == kind)
183 }
184} 160}
185 161
186impl ast::ImplDef { 162impl ast::ImplDef {
@@ -387,24 +363,9 @@ pub enum SelfParamKind {
387} 363}
388 364
389impl ast::SelfParam { 365impl ast::SelfParam {
390 pub fn self_kw_token(&self) -> SyntaxToken {
391 self.syntax()
392 .children_with_tokens()
393 .filter_map(|it| it.into_token())
394 .find(|it| it.kind() == T![self])
395 .expect("invalid tree: self param must have self")
396 }
397
398 pub fn kind(&self) -> SelfParamKind { 366 pub fn kind(&self) -> SelfParamKind {
399 let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == T![&]); 367 if self.amp().is_some() {
400 if borrowed { 368 if self.amp_mut_kw().is_some() {
401 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
402 if self
403 .syntax()
404 .children_with_tokens()
405 .skip_while(|n| n.kind() != T![&])
406 .any(|n| n.kind() == T![mut])
407 {
408 SelfParamKind::MutRef 369 SelfParamKind::MutRef
409 } else { 370 } else {
410 SelfParamKind::Ref 371 SelfParamKind::Ref
@@ -413,32 +374,23 @@ impl ast::SelfParam {
413 SelfParamKind::Owned 374 SelfParamKind::Owned
414 } 375 }
415 } 376 }
416}
417 377
418impl ast::LifetimeParam { 378 /// the "mut" in "mut self", not the one in "&mut self"
419 pub fn lifetime_token(&self) -> Option<SyntaxToken> { 379 pub fn mut_kw(&self) -> Option<ast::MutKw> {
420 self.syntax() 380 self.syntax()
421 .children_with_tokens() 381 .children_with_tokens()
422 .filter_map(|it| it.into_token()) 382 .filter_map(|it| it.into_token())
423 .find(|it| it.kind() == LIFETIME) 383 .take_while(|it| it.kind() != T![&])
384 .find_map(ast::MutKw::cast)
424 } 385 }
425}
426 386
427impl ast::TypeParam { 387 /// the "mut" in "&mut self", not the one in "mut self"
428 pub fn colon_token(&self) -> Option<SyntaxToken> { 388 pub fn amp_mut_kw(&self) -> Option<ast::MutKw> {
429 self.syntax() 389 self.syntax()
430 .children_with_tokens() 390 .children_with_tokens()
431 .filter_map(|it| it.into_token()) 391 .filter_map(|it| it.into_token())
432 .find(|it| it.kind() == T![:]) 392 .skip_while(|it| it.kind() != T![&])
433 } 393 .find_map(ast::MutKw::cast)
434}
435
436impl ast::WherePred {
437 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
438 self.syntax()
439 .children_with_tokens()
440 .filter_map(|it| it.into_token())
441 .find(|it| it.kind() == LIFETIME)
442 } 394 }
443} 395}
444 396
@@ -449,7 +401,7 @@ pub enum TypeBoundKind {
449 /// for<'a> ... 401 /// for<'a> ...
450 ForType(ast::ForType), 402 ForType(ast::ForType),
451 /// 'a 403 /// 'a
452 Lifetime(ast::SyntaxToken), 404 Lifetime(ast::Lifetime),
453} 405}
454 406
455impl ast::TypeBound { 407impl ast::TypeBound {
@@ -465,21 +417,28 @@ impl ast::TypeBound {
465 } 417 }
466 } 418 }
467 419
468 fn lifetime(&self) -> Option<SyntaxToken> { 420 pub fn has_question_mark(&self) -> bool {
469 self.syntax() 421 self.question().is_some()
470 .children_with_tokens()
471 .filter_map(|it| it.into_token())
472 .find(|it| it.kind() == LIFETIME)
473 } 422 }
474 423
475 pub fn question_mark_token(&self) -> Option<SyntaxToken> { 424 pub fn const_question(&self) -> Option<ast::Question> {
476 self.syntax() 425 self.syntax()
477 .children_with_tokens() 426 .children_with_tokens()
478 .filter_map(|it| it.into_token()) 427 .filter_map(|it| it.into_token())
479 .find(|it| it.kind() == T![?]) 428 .take_while(|it| it.kind() != T![const])
429 .find_map(ast::Question::cast)
480 } 430 }
481 pub fn has_question_mark(&self) -> bool { 431
482 self.question_mark_token().is_some() 432 pub fn question(&self) -> Option<ast::Question> {
433 if self.const_kw().is_some() {
434 self.syntax()
435 .children_with_tokens()
436 .filter_map(|it| it.into_token())
437 .skip_while(|it| it.kind() != T![const])
438 .find_map(ast::Question::cast)
439 } else {
440 child_token_opt(self)
441 }
483 } 442 }
484} 443}
485 444
@@ -493,6 +452,7 @@ pub enum VisibilityKind {
493 In(ast::Path), 452 In(ast::Path),
494 PubCrate, 453 PubCrate,
495 PubSuper, 454 PubSuper,
455 PubSelf,
496 Pub, 456 Pub,
497} 457}
498 458
@@ -504,6 +464,8 @@ impl ast::Visibility {
504 VisibilityKind::PubCrate 464 VisibilityKind::PubCrate
505 } else if self.is_pub_super() { 465 } else if self.is_pub_super() {
506 VisibilityKind::PubSuper 466 VisibilityKind::PubSuper
467 } else if self.is_pub_self() {
468 VisibilityKind::PubSuper
507 } else { 469 } else {
508 VisibilityKind::Pub 470 VisibilityKind::Pub
509 } 471 }
@@ -516,6 +478,10 @@ impl ast::Visibility {
516 fn is_pub_super(&self) -> bool { 478 fn is_pub_super(&self) -> bool {
517 self.syntax().children_with_tokens().any(|it| it.kind() == T![super]) 479 self.syntax().children_with_tokens().any(|it| it.kind() == T![super])
518 } 480 }
481
482 fn is_pub_self(&self) -> bool {
483 self.syntax().children_with_tokens().any(|it| it.kind() == T![self])
484 }
519} 485}
520 486
521impl ast::MacroCall { 487impl ast::MacroCall {
@@ -528,3 +494,41 @@ impl ast::MacroCall {
528 } 494 }
529 } 495 }
530} 496}
497
498impl ast::LifetimeParam {
499 pub fn lifetime_bounds(&self) -> impl Iterator<Item = ast::Lifetime> {
500 self.syntax()
501 .children_with_tokens()
502 .filter_map(|it| it.into_token())
503 .skip_while(|x| x.kind() != T![:])
504 .filter_map(ast::Lifetime::cast)
505 }
506}
507
508impl ast::RangePat {
509 pub fn start(&self) -> Option<ast::Pat> {
510 self.syntax()
511 .children_with_tokens()
512 .take_while(|it| !ast::RangeSeparator::can_cast_element(it.kind()))
513 .filter_map(|it| it.into_node())
514 .find_map(ast::Pat::cast)
515 }
516
517 pub fn end(&self) -> Option<ast::Pat> {
518 self.syntax()
519 .children_with_tokens()
520 .skip_while(|it| !ast::RangeSeparator::can_cast_element(it.kind()))
521 .filter_map(|it| it.into_node())
522 .find_map(ast::Pat::cast)
523 }
524}
525
526impl ast::TokenTree {
527 pub fn left_delimiter(&self) -> Option<ast::LeftDelimiter> {
528 self.syntax().first_child_or_token().and_then(ast::LeftDelimiter::cast_element)
529 }
530
531 pub fn right_delimiter(&self) -> Option<ast::RightDelimiter> {
532 self.syntax().last_child_or_token().and_then(ast::RightDelimiter::cast_element)
533 }
534}
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
index 576378306..e6f3a4ebb 100644
--- a/crates/ra_syntax/src/ast/traits.rs
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -4,9 +4,9 @@
4 4
5use itertools::Itertools; 5use itertools::Itertools;
6 6
7use crate::{ 7use crate::ast::{
8 ast::{self, child_opt, children, AstChildren, AstNode, AstToken}, 8 self, child_elements, child_opt, child_token_opt, child_tokens, children, AstChildElements,
9 syntax_node::SyntaxElementChildren, 9 AstChildTokens, AstChildren, AstNode, AstToken,
10}; 10};
11 11
12pub trait TypeAscriptionOwner: AstNode { 12pub trait TypeAscriptionOwner: AstNode {
@@ -31,6 +31,10 @@ pub trait LoopBodyOwner: AstNode {
31 fn loop_body(&self) -> Option<ast::BlockExpr> { 31 fn loop_body(&self) -> Option<ast::BlockExpr> {
32 child_opt(self) 32 child_opt(self)
33 } 33 }
34
35 fn label(&self) -> Option<ast::Label> {
36 child_opt(self)
37 }
34} 38}
35 39
36pub trait ArgListOwner: AstNode { 40pub trait ArgListOwner: AstNode {
@@ -65,6 +69,10 @@ pub trait TypeBoundsOwner: AstNode {
65 fn type_bound_list(&self) -> Option<ast::TypeBoundList> { 69 fn type_bound_list(&self) -> Option<ast::TypeBoundList> {
66 child_opt(self) 70 child_opt(self)
67 } 71 }
72
73 fn colon(&self) -> Option<ast::Colon> {
74 child_token_opt(self)
75 }
68} 76}
69 77
70pub trait AttrsOwner: AstNode { 78pub trait AttrsOwner: AstNode {
@@ -74,11 +82,14 @@ pub trait AttrsOwner: AstNode {
74 fn has_atom_attr(&self, atom: &str) -> bool { 82 fn has_atom_attr(&self, atom: &str) -> bool {
75 self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom) 83 self.attrs().filter_map(|x| x.as_simple_atom()).any(|x| x == atom)
76 } 84 }
85 fn attr_or_comments(&self) -> AstChildElements<ast::AttrOrComment> {
86 child_elements(self)
87 }
77} 88}
78 89
79pub trait DocCommentsOwner: AstNode { 90pub trait DocCommentsOwner: AstNode {
80 fn doc_comments(&self) -> CommentIter { 91 fn doc_comments(&self) -> AstChildTokens<ast::Comment> {
81 CommentIter { iter: self.syntax().children_with_tokens() } 92 child_tokens(self)
82 } 93 }
83 94
84 /// Returns the textual content of a doc comment block as a single string. 95 /// Returns the textual content of a doc comment block as a single string.
@@ -123,14 +134,3 @@ pub trait DocCommentsOwner: AstNode {
123 } 134 }
124 } 135 }
125} 136}
126
127pub struct CommentIter {
128 iter: SyntaxElementChildren,
129}
130
131impl Iterator for CommentIter {
132 type Item = ast::Comment;
133 fn next(&mut self) -> Option<ast::Comment> {
134 self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
135 }
136}