diff options
Diffstat (limited to 'crates')
98 files changed, 4565 insertions, 2139 deletions
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index c3e653299..279163257 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs | |||
@@ -10,7 +10,7 @@ use ra_syntax::{ | |||
10 | }; | 10 | }; |
11 | use ra_text_edit::TextEditBuilder; | 11 | use ra_text_edit::TextEditBuilder; |
12 | 12 | ||
13 | use crate::{AssistAction, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; | 13 | use crate::{AssistAction, AssistFile, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; |
14 | use algo::SyntaxRewriter; | 14 | use algo::SyntaxRewriter; |
15 | 15 | ||
16 | #[derive(Clone, Debug)] | 16 | #[derive(Clone, Debug)] |
@@ -180,6 +180,7 @@ pub(crate) struct ActionBuilder { | |||
180 | edit: TextEditBuilder, | 180 | edit: TextEditBuilder, |
181 | cursor_position: Option<TextUnit>, | 181 | cursor_position: Option<TextUnit>, |
182 | target: Option<TextRange>, | 182 | target: Option<TextRange>, |
183 | file: AssistFile, | ||
183 | } | 184 | } |
184 | 185 | ||
185 | impl ActionBuilder { | 186 | impl ActionBuilder { |
@@ -241,11 +242,16 @@ impl ActionBuilder { | |||
241 | algo::diff(&node, &new).into_text_edit(&mut self.edit) | 242 | algo::diff(&node, &new).into_text_edit(&mut self.edit) |
242 | } | 243 | } |
243 | 244 | ||
245 | pub(crate) fn set_file(&mut self, assist_file: AssistFile) { | ||
246 | self.file = assist_file | ||
247 | } | ||
248 | |||
244 | fn build(self) -> AssistAction { | 249 | fn build(self) -> AssistAction { |
245 | AssistAction { | 250 | AssistAction { |
246 | edit: self.edit.finish(), | 251 | edit: self.edit.finish(), |
247 | cursor_position: self.cursor_position, | 252 | cursor_position: self.cursor_position, |
248 | target: self.target, | 253 | target: self.target, |
254 | file: self.file, | ||
249 | } | 255 | } |
250 | } | 256 | } |
251 | } | 257 | } |
diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index b39e60870..e4fa9ee36 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs | |||
@@ -66,7 +66,7 @@ fn doctest_add_function() { | |||
66 | struct Baz; | 66 | struct Baz; |
67 | fn baz() -> Baz { Baz } | 67 | fn baz() -> Baz { Baz } |
68 | fn foo() { | 68 | fn foo() { |
69 | bar<|>("", baz()); | 69 | bar<|>("", baz()); |
70 | } | 70 | } |
71 | 71 | ||
72 | "#####, | 72 | "#####, |
@@ -74,7 +74,7 @@ fn foo() { | |||
74 | struct Baz; | 74 | struct Baz; |
75 | fn baz() -> Baz { Baz } | 75 | fn baz() -> Baz { Baz } |
76 | fn foo() { | 76 | fn foo() { |
77 | bar("", baz()); | 77 | bar("", baz()); |
78 | } | 78 | } |
79 | 79 | ||
80 | fn bar(arg: &str, baz: Baz) { | 80 | fn bar(arg: &str, baz: Baz) { |
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index d86d804b2..6c56d93d8 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs | |||
@@ -52,21 +52,22 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option<Assist> { | |||
52 | } | 52 | } |
53 | // Infer type | 53 | // Infer type |
54 | let ty = ctx.sema.type_of_expr(&expr)?; | 54 | let ty = ctx.sema.type_of_expr(&expr)?; |
55 | // Assist not applicable if the type is unknown | 55 | |
56 | if ty.contains_unknown() { | 56 | if ty.contains_unknown() || ty.is_closure() { |
57 | return None; | 57 | return None; |
58 | } | 58 | } |
59 | 59 | ||
60 | let db = ctx.db; | 60 | let db = ctx.db; |
61 | let new_type_string = ty.display_truncated(db, None).to_string(); | ||
61 | ctx.add_assist( | 62 | ctx.add_assist( |
62 | AssistId("add_explicit_type"), | 63 | AssistId("add_explicit_type"), |
63 | format!("Insert explicit type '{}'", ty.display(db)), | 64 | format!("Insert explicit type '{}'", new_type_string), |
64 | |edit| { | 65 | |edit| { |
65 | edit.target(pat_range); | 66 | edit.target(pat_range); |
66 | if let Some(ascribed_ty) = ascribed_ty { | 67 | if let Some(ascribed_ty) = ascribed_ty { |
67 | edit.replace(ascribed_ty.syntax().text_range(), format!("{}", ty.display(db))); | 68 | edit.replace(ascribed_ty.syntax().text_range(), new_type_string); |
68 | } else { | 69 | } else { |
69 | edit.insert(name_range.end(), format!(": {}", ty.display(db))); | 70 | edit.insert(name_range.end(), format!(": {}", new_type_string)); |
70 | } | 71 | } |
71 | }, | 72 | }, |
72 | ) | 73 | ) |
@@ -174,4 +175,41 @@ mod tests { | |||
174 | "fn f() <|>{let a = match 1 {2 => 3, 3 => 5};}", | 175 | "fn f() <|>{let a = match 1 {2 => 3, 3 => 5};}", |
175 | ) | 176 | ) |
176 | } | 177 | } |
178 | |||
179 | #[test] | ||
180 | fn closure_parameters_are_not_added() { | ||
181 | check_assist_not_applicable( | ||
182 | add_explicit_type, | ||
183 | r#" | ||
184 | fn main() { | ||
185 | let multiply_by_two<|> = |i| i * 3; | ||
186 | let six = multiply_by_two(2); | ||
187 | }"#, | ||
188 | ) | ||
189 | } | ||
190 | |||
191 | #[test] | ||
192 | fn default_generics_should_not_be_added() { | ||
193 | check_assist( | ||
194 | add_explicit_type, | ||
195 | r#" | ||
196 | struct Test<K, T = u8> { | ||
197 | k: K, | ||
198 | t: T, | ||
199 | } | ||
200 | |||
201 | fn main() { | ||
202 | let test<|> = Test { t: 23, k: 33 }; | ||
203 | }"#, | ||
204 | r#" | ||
205 | struct Test<K, T = u8> { | ||
206 | k: K, | ||
207 | t: T, | ||
208 | } | ||
209 | |||
210 | fn main() { | ||
211 | let test<|>: Test<i32> = Test { t: 23, k: 33 }; | ||
212 | }"#, | ||
213 | ); | ||
214 | } | ||
177 | } | 215 | } |
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs index 864373aa5..0621487e8 100644 --- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs +++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs | |||
@@ -98,7 +98,7 @@ fn already_has_from_impl( | |||
98 | }; | 98 | }; |
99 | let var_ty = hir_enum_var.fields(sema.db)[0].signature_ty(sema.db); | 99 | let var_ty = hir_enum_var.fields(sema.db)[0].signature_ty(sema.db); |
100 | 100 | ||
101 | e_ty.impls_trait(sema.db, from_trait, &[var_ty.clone()]) | 101 | e_ty.impls_trait(sema.db, from_trait, &[var_ty]) |
102 | } | 102 | } |
103 | 103 | ||
104 | #[cfg(test)] | 104 | #[cfg(test)] |
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs index ad4ab66ed..f185cffdb 100644 --- a/crates/ra_assists/src/handlers/add_function.rs +++ b/crates/ra_assists/src/handlers/add_function.rs | |||
@@ -3,8 +3,8 @@ use ra_syntax::{ | |||
3 | SyntaxKind, SyntaxNode, TextUnit, | 3 | SyntaxKind, SyntaxNode, TextUnit, |
4 | }; | 4 | }; |
5 | 5 | ||
6 | use crate::{Assist, AssistCtx, AssistId}; | 6 | use crate::{Assist, AssistCtx, AssistFile, AssistId}; |
7 | use ast::{edit::IndentLevel, ArgListOwner, CallExpr, Expr}; | 7 | use ast::{edit::IndentLevel, ArgListOwner, ModuleItemOwner}; |
8 | use hir::HirDisplay; | 8 | use hir::HirDisplay; |
9 | use rustc_hash::{FxHashMap, FxHashSet}; | 9 | use rustc_hash::{FxHashMap, FxHashSet}; |
10 | 10 | ||
@@ -16,7 +16,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
16 | // struct Baz; | 16 | // struct Baz; |
17 | // fn baz() -> Baz { Baz } | 17 | // fn baz() -> Baz { Baz } |
18 | // fn foo() { | 18 | // fn foo() { |
19 | // bar<|>("", baz()); | 19 | // bar<|>("", baz()); |
20 | // } | 20 | // } |
21 | // | 21 | // |
22 | // ``` | 22 | // ``` |
@@ -25,7 +25,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; | |||
25 | // struct Baz; | 25 | // struct Baz; |
26 | // fn baz() -> Baz { Baz } | 26 | // fn baz() -> Baz { Baz } |
27 | // fn foo() { | 27 | // fn foo() { |
28 | // bar("", baz()); | 28 | // bar("", baz()); |
29 | // } | 29 | // } |
30 | // | 30 | // |
31 | // fn bar(arg: &str, baz: Baz) { | 31 | // fn bar(arg: &str, baz: Baz) { |
@@ -38,21 +38,30 @@ pub(crate) fn add_function(ctx: AssistCtx) -> Option<Assist> { | |||
38 | let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?; | 38 | let call = path_expr.syntax().parent().and_then(ast::CallExpr::cast)?; |
39 | let path = path_expr.path()?; | 39 | let path = path_expr.path()?; |
40 | 40 | ||
41 | if path.qualifier().is_some() { | ||
42 | return None; | ||
43 | } | ||
44 | |||
45 | if ctx.sema.resolve_path(&path).is_some() { | 41 | if ctx.sema.resolve_path(&path).is_some() { |
46 | // The function call already resolves, no need to add a function | 42 | // The function call already resolves, no need to add a function |
47 | return None; | 43 | return None; |
48 | } | 44 | } |
49 | 45 | ||
50 | let function_builder = FunctionBuilder::from_call(&ctx, &call)?; | 46 | let target_module = if let Some(qualifier) = path.qualifier() { |
47 | if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) = | ||
48 | ctx.sema.resolve_path(&qualifier) | ||
49 | { | ||
50 | Some(module.definition_source(ctx.sema.db)) | ||
51 | } else { | ||
52 | return None; | ||
53 | } | ||
54 | } else { | ||
55 | None | ||
56 | }; | ||
57 | |||
58 | let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?; | ||
51 | 59 | ||
52 | ctx.add_assist(AssistId("add_function"), "Add function", |edit| { | 60 | ctx.add_assist(AssistId("add_function"), "Add function", |edit| { |
53 | edit.target(call.syntax().text_range()); | 61 | edit.target(call.syntax().text_range()); |
54 | 62 | ||
55 | if let Some(function_template) = function_builder.render() { | 63 | if let Some(function_template) = function_builder.render() { |
64 | edit.set_file(function_template.file); | ||
56 | edit.set_cursor(function_template.cursor_offset); | 65 | edit.set_cursor(function_template.cursor_offset); |
57 | edit.insert(function_template.insert_offset, function_template.fn_def.to_string()); | 66 | edit.insert(function_template.insert_offset, function_template.fn_def.to_string()); |
58 | } | 67 | } |
@@ -63,29 +72,67 @@ struct FunctionTemplate { | |||
63 | insert_offset: TextUnit, | 72 | insert_offset: TextUnit, |
64 | cursor_offset: TextUnit, | 73 | cursor_offset: TextUnit, |
65 | fn_def: ast::SourceFile, | 74 | fn_def: ast::SourceFile, |
75 | file: AssistFile, | ||
66 | } | 76 | } |
67 | 77 | ||
68 | struct FunctionBuilder { | 78 | struct FunctionBuilder { |
69 | append_fn_at: SyntaxNode, | 79 | target: GeneratedFunctionTarget, |
70 | fn_name: ast::Name, | 80 | fn_name: ast::Name, |
71 | type_params: Option<ast::TypeParamList>, | 81 | type_params: Option<ast::TypeParamList>, |
72 | params: ast::ParamList, | 82 | params: ast::ParamList, |
83 | file: AssistFile, | ||
84 | needs_pub: bool, | ||
73 | } | 85 | } |
74 | 86 | ||
75 | impl FunctionBuilder { | 87 | impl FunctionBuilder { |
76 | fn from_call(ctx: &AssistCtx, call: &ast::CallExpr) -> Option<Self> { | 88 | /// Prepares a generated function that matches `call` in `generate_in` |
77 | let append_fn_at = next_space_for_fn(&call)?; | 89 | /// (or as close to `call` as possible, if `generate_in` is `None`) |
78 | let fn_name = fn_name(&call)?; | 90 | fn from_call( |
91 | ctx: &AssistCtx, | ||
92 | call: &ast::CallExpr, | ||
93 | path: &ast::Path, | ||
94 | target_module: Option<hir::InFile<hir::ModuleSource>>, | ||
95 | ) -> Option<Self> { | ||
96 | let needs_pub = target_module.is_some(); | ||
97 | let mut file = AssistFile::default(); | ||
98 | let target = if let Some(target_module) = target_module { | ||
99 | let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, target_module)?; | ||
100 | file = in_file; | ||
101 | target | ||
102 | } else { | ||
103 | next_space_for_fn_after_call_site(&call)? | ||
104 | }; | ||
105 | let fn_name = fn_name(&path)?; | ||
79 | let (type_params, params) = fn_args(ctx, &call)?; | 106 | let (type_params, params) = fn_args(ctx, &call)?; |
80 | Some(Self { append_fn_at, fn_name, type_params, params }) | 107 | Some(Self { target, fn_name, type_params, params, file, needs_pub }) |
81 | } | 108 | } |
109 | |||
82 | fn render(self) -> Option<FunctionTemplate> { | 110 | fn render(self) -> Option<FunctionTemplate> { |
83 | let placeholder_expr = ast::make::expr_todo(); | 111 | let placeholder_expr = ast::make::expr_todo(); |
84 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); | 112 | let fn_body = ast::make::block_expr(vec![], Some(placeholder_expr)); |
85 | let fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); | 113 | let mut fn_def = ast::make::fn_def(self.fn_name, self.type_params, self.params, fn_body); |
86 | let fn_def = ast::make::add_newlines(2, fn_def); | 114 | if self.needs_pub { |
87 | let fn_def = IndentLevel::from_node(&self.append_fn_at).increase_indent(fn_def); | 115 | fn_def = ast::make::add_pub_crate_modifier(fn_def); |
88 | let insert_offset = self.append_fn_at.text_range().end(); | 116 | } |
117 | |||
118 | let (fn_def, insert_offset) = match self.target { | ||
119 | GeneratedFunctionTarget::BehindItem(it) => { | ||
120 | let with_leading_blank_line = ast::make::add_leading_newlines(2, fn_def); | ||
121 | let indented = IndentLevel::from_node(&it).increase_indent(with_leading_blank_line); | ||
122 | (indented, it.text_range().end()) | ||
123 | } | ||
124 | GeneratedFunctionTarget::InEmptyItemList(it) => { | ||
125 | let indent_once = IndentLevel(1); | ||
126 | let indent = IndentLevel::from_node(it.syntax()); | ||
127 | |||
128 | let fn_def = ast::make::add_leading_newlines(1, fn_def); | ||
129 | let fn_def = indent_once.increase_indent(fn_def); | ||
130 | let fn_def = ast::make::add_trailing_newlines(1, fn_def); | ||
131 | let fn_def = indent.increase_indent(fn_def); | ||
132 | (fn_def, it.syntax().text_range().start() + TextUnit::from_usize(1)) | ||
133 | } | ||
134 | }; | ||
135 | |||
89 | let cursor_offset_from_fn_start = fn_def | 136 | let cursor_offset_from_fn_start = fn_def |
90 | .syntax() | 137 | .syntax() |
91 | .descendants() | 138 | .descendants() |
@@ -94,19 +141,24 @@ impl FunctionBuilder { | |||
94 | .text_range() | 141 | .text_range() |
95 | .start(); | 142 | .start(); |
96 | let cursor_offset = insert_offset + cursor_offset_from_fn_start; | 143 | let cursor_offset = insert_offset + cursor_offset_from_fn_start; |
97 | Some(FunctionTemplate { insert_offset, cursor_offset, fn_def }) | 144 | Some(FunctionTemplate { insert_offset, cursor_offset, fn_def, file: self.file }) |
98 | } | 145 | } |
99 | } | 146 | } |
100 | 147 | ||
101 | fn fn_name(call: &CallExpr) -> Option<ast::Name> { | 148 | enum GeneratedFunctionTarget { |
102 | let name = call.expr()?.syntax().to_string(); | 149 | BehindItem(SyntaxNode), |
150 | InEmptyItemList(ast::ItemList), | ||
151 | } | ||
152 | |||
153 | fn fn_name(call: &ast::Path) -> Option<ast::Name> { | ||
154 | let name = call.segment()?.syntax().to_string(); | ||
103 | Some(ast::make::name(&name)) | 155 | Some(ast::make::name(&name)) |
104 | } | 156 | } |
105 | 157 | ||
106 | /// Computes the type variables and arguments required for the generated function | 158 | /// Computes the type variables and arguments required for the generated function |
107 | fn fn_args( | 159 | fn fn_args( |
108 | ctx: &AssistCtx, | 160 | ctx: &AssistCtx, |
109 | call: &CallExpr, | 161 | call: &ast::CallExpr, |
110 | ) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> { | 162 | ) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> { |
111 | let mut arg_names = Vec::new(); | 163 | let mut arg_names = Vec::new(); |
112 | let mut arg_types = Vec::new(); | 164 | let mut arg_types = Vec::new(); |
@@ -158,9 +210,9 @@ fn deduplicate_arg_names(arg_names: &mut Vec<String>) { | |||
158 | } | 210 | } |
159 | } | 211 | } |
160 | 212 | ||
161 | fn fn_arg_name(fn_arg: &Expr) -> Option<String> { | 213 | fn fn_arg_name(fn_arg: &ast::Expr) -> Option<String> { |
162 | match fn_arg { | 214 | match fn_arg { |
163 | Expr::CastExpr(cast_expr) => fn_arg_name(&cast_expr.expr()?), | 215 | ast::Expr::CastExpr(cast_expr) => fn_arg_name(&cast_expr.expr()?), |
164 | _ => Some( | 216 | _ => Some( |
165 | fn_arg | 217 | fn_arg |
166 | .syntax() | 218 | .syntax() |
@@ -172,7 +224,7 @@ fn fn_arg_name(fn_arg: &Expr) -> Option<String> { | |||
172 | } | 224 | } |
173 | } | 225 | } |
174 | 226 | ||
175 | fn fn_arg_type(ctx: &AssistCtx, fn_arg: &Expr) -> Option<String> { | 227 | fn fn_arg_type(ctx: &AssistCtx, fn_arg: &ast::Expr) -> Option<String> { |
176 | let ty = ctx.sema.type_of_expr(fn_arg)?; | 228 | let ty = ctx.sema.type_of_expr(fn_arg)?; |
177 | if ty.is_unknown() { | 229 | if ty.is_unknown() { |
178 | return None; | 230 | return None; |
@@ -184,7 +236,7 @@ fn fn_arg_type(ctx: &AssistCtx, fn_arg: &Expr) -> Option<String> { | |||
184 | /// directly after the current block | 236 | /// directly after the current block |
185 | /// We want to write the generated function directly after | 237 | /// We want to write the generated function directly after |
186 | /// fns, impls or macro calls, but inside mods | 238 | /// fns, impls or macro calls, but inside mods |
187 | fn next_space_for_fn(expr: &CallExpr) -> Option<SyntaxNode> { | 239 | fn next_space_for_fn_after_call_site(expr: &ast::CallExpr) -> Option<GeneratedFunctionTarget> { |
188 | let mut ancestors = expr.syntax().ancestors().peekable(); | 240 | let mut ancestors = expr.syntax().ancestors().peekable(); |
189 | let mut last_ancestor: Option<SyntaxNode> = None; | 241 | let mut last_ancestor: Option<SyntaxNode> = None; |
190 | while let Some(next_ancestor) = ancestors.next() { | 242 | while let Some(next_ancestor) = ancestors.next() { |
@@ -201,7 +253,32 @@ fn next_space_for_fn(expr: &CallExpr) -> Option<SyntaxNode> { | |||
201 | } | 253 | } |
202 | last_ancestor = Some(next_ancestor); | 254 | last_ancestor = Some(next_ancestor); |
203 | } | 255 | } |
204 | last_ancestor | 256 | last_ancestor.map(GeneratedFunctionTarget::BehindItem) |
257 | } | ||
258 | |||
259 | fn next_space_for_fn_in_module( | ||
260 | db: &dyn hir::db::AstDatabase, | ||
261 | module: hir::InFile<hir::ModuleSource>, | ||
262 | ) -> Option<(AssistFile, GeneratedFunctionTarget)> { | ||
263 | let file = module.file_id.original_file(db); | ||
264 | let assist_file = AssistFile::TargetFile(file); | ||
265 | let assist_item = match module.value { | ||
266 | hir::ModuleSource::SourceFile(it) => { | ||
267 | if let Some(last_item) = it.items().last() { | ||
268 | GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) | ||
269 | } else { | ||
270 | GeneratedFunctionTarget::BehindItem(it.syntax().clone()) | ||
271 | } | ||
272 | } | ||
273 | hir::ModuleSource::Module(it) => { | ||
274 | if let Some(last_item) = it.item_list().and_then(|it| it.items().last()) { | ||
275 | GeneratedFunctionTarget::BehindItem(last_item.syntax().clone()) | ||
276 | } else { | ||
277 | GeneratedFunctionTarget::InEmptyItemList(it.item_list()?) | ||
278 | } | ||
279 | } | ||
280 | }; | ||
281 | Some((assist_file, assist_item)) | ||
205 | } | 282 | } |
206 | 283 | ||
207 | #[cfg(test)] | 284 | #[cfg(test)] |
@@ -714,6 +791,111 @@ fn bar(baz_1: Baz, baz_2: Baz, arg_1: &str, arg_2: &str) { | |||
714 | } | 791 | } |
715 | 792 | ||
716 | #[test] | 793 | #[test] |
794 | fn add_function_in_module() { | ||
795 | check_assist( | ||
796 | add_function, | ||
797 | r" | ||
798 | mod bar {} | ||
799 | |||
800 | fn foo() { | ||
801 | bar::my_fn<|>() | ||
802 | } | ||
803 | ", | ||
804 | r" | ||
805 | mod bar { | ||
806 | pub(crate) fn my_fn() { | ||
807 | <|>todo!() | ||
808 | } | ||
809 | } | ||
810 | |||
811 | fn foo() { | ||
812 | bar::my_fn() | ||
813 | } | ||
814 | ", | ||
815 | ) | ||
816 | } | ||
817 | |||
818 | #[test] | ||
819 | fn add_function_in_module_containing_other_items() { | ||
820 | check_assist( | ||
821 | add_function, | ||
822 | r" | ||
823 | mod bar { | ||
824 | fn something_else() {} | ||
825 | } | ||
826 | |||
827 | fn foo() { | ||
828 | bar::my_fn<|>() | ||
829 | } | ||
830 | ", | ||
831 | r" | ||
832 | mod bar { | ||
833 | fn something_else() {} | ||
834 | |||
835 | pub(crate) fn my_fn() { | ||
836 | <|>todo!() | ||
837 | } | ||
838 | } | ||
839 | |||
840 | fn foo() { | ||
841 | bar::my_fn() | ||
842 | } | ||
843 | ", | ||
844 | ) | ||
845 | } | ||
846 | |||
847 | #[test] | ||
848 | fn add_function_in_nested_module() { | ||
849 | check_assist( | ||
850 | add_function, | ||
851 | r" | ||
852 | mod bar { | ||
853 | mod baz {} | ||
854 | } | ||
855 | |||
856 | fn foo() { | ||
857 | bar::baz::my_fn<|>() | ||
858 | } | ||
859 | ", | ||
860 | r" | ||
861 | mod bar { | ||
862 | mod baz { | ||
863 | pub(crate) fn my_fn() { | ||
864 | <|>todo!() | ||
865 | } | ||
866 | } | ||
867 | } | ||
868 | |||
869 | fn foo() { | ||
870 | bar::baz::my_fn() | ||
871 | } | ||
872 | ", | ||
873 | ) | ||
874 | } | ||
875 | |||
876 | #[test] | ||
877 | fn add_function_in_another_file() { | ||
878 | check_assist( | ||
879 | add_function, | ||
880 | r" | ||
881 | //- /main.rs | ||
882 | mod foo; | ||
883 | |||
884 | fn main() { | ||
885 | foo::bar<|>() | ||
886 | } | ||
887 | //- /foo.rs | ||
888 | ", | ||
889 | r" | ||
890 | |||
891 | |||
892 | pub(crate) fn bar() { | ||
893 | <|>todo!() | ||
894 | }", | ||
895 | ) | ||
896 | } | ||
897 | |||
898 | #[test] | ||
717 | fn add_function_not_applicable_if_function_already_exists() { | 899 | fn add_function_not_applicable_if_function_already_exists() { |
718 | check_assist_not_applicable( | 900 | check_assist_not_applicable( |
719 | add_function, | 901 | add_function, |
diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index 8d0f7e922..8c09e6bcd 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs | |||
@@ -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().into()).is_some() { | 127 | if ast::Stmt::cast(node.clone()).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 ef0ce0586..4be1238f1 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs | |||
@@ -30,7 +30,7 @@ pub(crate) fn merge_imports(ctx: AssistCtx) -> Option<Assist> { | |||
30 | .filter_map(|dir| neighbor(&use_item, dir)) | 30 | .filter_map(|dir| neighbor(&use_item, dir)) |
31 | .filter_map(|it| Some((it.clone(), it.use_tree()?))) | 31 | .filter_map(|it| Some((it.clone(), it.use_tree()?))) |
32 | .find_map(|(use_item, use_tree)| { | 32 | .find_map(|(use_item, use_tree)| { |
33 | Some((try_merge_trees(&tree, &use_tree)?, use_item.clone())) | 33 | Some((try_merge_trees(&tree, &use_tree)?, use_item)) |
34 | })?; | 34 | })?; |
35 | 35 | ||
36 | rewriter.replace_ast(&tree, &merged); | 36 | rewriter.replace_ast(&tree, &merged); |
diff --git a/crates/ra_assists/src/handlers/split_import.rs b/crates/ra_assists/src/handlers/split_import.rs index d9244f22d..f25826796 100644 --- a/crates/ra_assists/src/handlers/split_import.rs +++ b/crates/ra_assists/src/handlers/split_import.rs | |||
@@ -37,7 +37,7 @@ pub(crate) fn split_import(ctx: AssistCtx) -> Option<Assist> { | |||
37 | 37 | ||
38 | #[cfg(test)] | 38 | #[cfg(test)] |
39 | mod tests { | 39 | mod tests { |
40 | use crate::helpers::{check_assist, check_assist_target}; | 40 | use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; |
41 | 41 | ||
42 | use super::*; | 42 | use super::*; |
43 | 43 | ||
@@ -63,4 +63,9 @@ mod tests { | |||
63 | fn split_import_target() { | 63 | fn split_import_target() { |
64 | check_assist_target(split_import, "use crate::<|>db::{RootDatabase, FileSymbol}", "::"); | 64 | check_assist_target(split_import, "use crate::<|>db::{RootDatabase, FileSymbol}", "::"); |
65 | } | 65 | } |
66 | |||
67 | #[test] | ||
68 | fn issue4044() { | ||
69 | check_assist_not_applicable(split_import, "use crate::<|>:::self;") | ||
70 | } | ||
66 | } | 71 | } |
diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index a00136da1..ccc95735f 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs | |||
@@ -17,7 +17,7 @@ mod doc_tests; | |||
17 | pub mod utils; | 17 | pub mod utils; |
18 | pub mod ast_transform; | 18 | pub mod ast_transform; |
19 | 19 | ||
20 | use ra_db::FileRange; | 20 | use ra_db::{FileId, FileRange}; |
21 | use ra_ide_db::RootDatabase; | 21 | use ra_ide_db::RootDatabase; |
22 | use ra_syntax::{TextRange, TextUnit}; | 22 | use ra_syntax::{TextRange, TextUnit}; |
23 | use ra_text_edit::TextEdit; | 23 | use ra_text_edit::TextEdit; |
@@ -54,6 +54,7 @@ pub struct AssistAction { | |||
54 | pub cursor_position: Option<TextUnit>, | 54 | pub cursor_position: Option<TextUnit>, |
55 | // FIXME: This belongs to `AssistLabel` | 55 | // FIXME: This belongs to `AssistLabel` |
56 | pub target: Option<TextRange>, | 56 | pub target: Option<TextRange>, |
57 | pub file: AssistFile, | ||
57 | } | 58 | } |
58 | 59 | ||
59 | #[derive(Debug, Clone)] | 60 | #[derive(Debug, Clone)] |
@@ -63,6 +64,18 @@ pub struct ResolvedAssist { | |||
63 | pub action: AssistAction, | 64 | pub action: AssistAction, |
64 | } | 65 | } |
65 | 66 | ||
67 | #[derive(Debug, Clone, Copy)] | ||
68 | pub enum AssistFile { | ||
69 | CurrentFile, | ||
70 | TargetFile(FileId), | ||
71 | } | ||
72 | |||
73 | impl Default for AssistFile { | ||
74 | fn default() -> Self { | ||
75 | Self::CurrentFile | ||
76 | } | ||
77 | } | ||
78 | |||
66 | /// Return all the assists applicable at the given position. | 79 | /// Return all the assists applicable at the given position. |
67 | /// | 80 | /// |
68 | /// Assists are returned in the "unresolved" state, that is only labels are | 81 | /// Assists are returned in the "unresolved" state, that is only labels are |
@@ -184,7 +197,7 @@ mod helpers { | |||
184 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; | 197 | use ra_ide_db::{symbol_index::SymbolsDatabase, RootDatabase}; |
185 | use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; | 198 | use test_utils::{add_cursor, assert_eq_text, extract_range_or_offset, RangeOrOffset}; |
186 | 199 | ||
187 | use crate::{AssistCtx, AssistHandler}; | 200 | use crate::{AssistCtx, AssistFile, AssistHandler}; |
188 | use hir::Semantics; | 201 | use hir::Semantics; |
189 | 202 | ||
190 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { | 203 | pub(crate) fn with_single_file(text: &str) -> (RootDatabase, FileId) { |
@@ -246,7 +259,13 @@ mod helpers { | |||
246 | (Some(assist), ExpectedResult::After(after)) => { | 259 | (Some(assist), ExpectedResult::After(after)) => { |
247 | let action = assist.0[0].action.clone().unwrap(); | 260 | let action = assist.0[0].action.clone().unwrap(); |
248 | 261 | ||
249 | let mut actual = action.edit.apply(&text_without_caret); | 262 | let assisted_file_text = if let AssistFile::TargetFile(file_id) = action.file { |
263 | db.file_text(file_id).as_ref().to_owned() | ||
264 | } else { | ||
265 | text_without_caret | ||
266 | }; | ||
267 | |||
268 | let mut actual = action.edit.apply(&assisted_file_text); | ||
250 | match action.cursor_position { | 269 | match action.cursor_position { |
251 | None => { | 270 | None => { |
252 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { | 271 | if let RangeOrOffset::Offset(before_cursor_pos) = range_or_offset { |
diff --git a/crates/ra_db/src/fixture.rs b/crates/ra_db/src/fixture.rs index 7777ce81e..8248684ee 100644 --- a/crates/ra_db/src/fixture.rs +++ b/crates/ra_db/src/fixture.rs | |||
@@ -235,7 +235,7 @@ fn parse_meta(meta: &str) -> ParsedMeta { | |||
235 | "env" => { | 235 | "env" => { |
236 | for key in value.split(',') { | 236 | for key in value.split(',') { |
237 | if let Some((k, v)) = split1(key, '=') { | 237 | if let Some((k, v)) = split1(key, '=') { |
238 | env.set(k.into(), v.into()); | 238 | env.set(k, v.into()); |
239 | } | 239 | } |
240 | } | 240 | } |
241 | } | 241 | } |
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 5ddce98c6..ab14e2d5e 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -327,7 +327,7 @@ impl ExternSource { | |||
327 | self.extern_paths.iter().find_map(|(root_path, id)| { | 327 | self.extern_paths.iter().find_map(|(root_path, id)| { |
328 | if let Ok(rel_path) = path.strip_prefix(root_path) { | 328 | if let Ok(rel_path) = path.strip_prefix(root_path) { |
329 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; | 329 | let rel_path = RelativePathBuf::from_path(rel_path).ok()?; |
330 | Some((id.clone(), rel_path)) | 330 | Some((*id, rel_path)) |
331 | } else { | 331 | } else { |
332 | None | 332 | None |
333 | } | 333 | } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 3801fce23..43f932e20 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -759,6 +759,17 @@ impl MacroDef { | |||
759 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 759 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
760 | self.source(db).value.name().map(|it| it.as_name()) | 760 | self.source(db).value.name().map(|it| it.as_name()) |
761 | } | 761 | } |
762 | |||
763 | /// Indicate it is a proc-macro | ||
764 | pub fn is_proc_macro(&self) -> bool { | ||
765 | match self.id.kind { | ||
766 | hir_expand::MacroDefKind::Declarative => false, | ||
767 | hir_expand::MacroDefKind::BuiltIn(_) => false, | ||
768 | hir_expand::MacroDefKind::BuiltInDerive(_) => false, | ||
769 | hir_expand::MacroDefKind::BuiltInEager(_) => false, | ||
770 | hir_expand::MacroDefKind::CustomDerive(_) => true, | ||
771 | } | ||
772 | } | ||
762 | } | 773 | } |
763 | 774 | ||
764 | /// Invariant: `inner.as_assoc_item(db).is_some()` | 775 | /// Invariant: `inner.as_assoc_item(db).is_some()` |
@@ -1121,6 +1132,10 @@ impl Type { | |||
1121 | Some(self.ty.value.as_callable()?.0) | 1132 | Some(self.ty.value.as_callable()?.0) |
1122 | } | 1133 | } |
1123 | 1134 | ||
1135 | pub fn is_closure(&self) -> bool { | ||
1136 | matches!(&self.ty.value, Ty::Apply(ApplicationTy { ctor: TypeCtor::Closure { .. }, .. })) | ||
1137 | } | ||
1138 | |||
1124 | pub fn contains_unknown(&self) -> bool { | 1139 | pub fn contains_unknown(&self) -> bool { |
1125 | return go(&self.ty.value); | 1140 | return go(&self.ty.value); |
1126 | 1141 | ||
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs index 0b477f0e9..5d6edc45c 100644 --- a/crates/ra_hir/src/semantics.rs +++ b/crates/ra_hir/src/semantics.rs | |||
@@ -195,6 +195,10 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { | |||
195 | self.analyze(field.syntax()).resolve_record_field(self.db, field) | 195 | self.analyze(field.syntax()).resolve_record_field(self.db, field) |
196 | } | 196 | } |
197 | 197 | ||
198 | pub fn resolve_record_field_pat(&self, field: &ast::RecordFieldPat) -> Option<StructField> { | ||
199 | self.analyze(field.syntax()).resolve_record_field_pat(self.db, field) | ||
200 | } | ||
201 | |||
198 | pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { | 202 | pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<MacroDef> { |
199 | let sa = self.analyze(macro_call.syntax()); | 203 | let sa = self.analyze(macro_call.syntax()); |
200 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); | 204 | let macro_call = self.find_file(macro_call.syntax().clone()).with_value(macro_call); |
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs index 23af400b8..0ed6d0958 100644 --- a/crates/ra_hir/src/source_analyzer.rs +++ b/crates/ra_hir/src/source_analyzer.rs | |||
@@ -95,6 +95,7 @@ impl SourceAnalyzer { | |||
95 | } | 95 | } |
96 | 96 | ||
97 | fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { | 97 | fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { |
98 | // FIXME: macros, see `expr_id` | ||
98 | let src = InFile { file_id: self.file_id, value: pat }; | 99 | let src = InFile { file_id: self.file_id, value: pat }; |
99 | self.body_source_map.as_ref()?.node_pat(src) | 100 | self.body_source_map.as_ref()?.node_pat(src) |
100 | } | 101 | } |
@@ -167,6 +168,16 @@ impl SourceAnalyzer { | |||
167 | Some((struct_field.into(), local)) | 168 | Some((struct_field.into(), local)) |
168 | } | 169 | } |
169 | 170 | ||
171 | pub(crate) fn resolve_record_field_pat( | ||
172 | &self, | ||
173 | _db: &dyn HirDatabase, | ||
174 | field: &ast::RecordFieldPat, | ||
175 | ) -> Option<StructField> { | ||
176 | let pat_id = self.pat_id(&field.pat()?)?; | ||
177 | let struct_field = self.infer.as_ref()?.record_field_pat_resolution(pat_id)?; | ||
178 | Some(struct_field.into()) | ||
179 | } | ||
180 | |||
170 | pub(crate) fn resolve_macro_call( | 181 | pub(crate) fn resolve_macro_call( |
171 | &self, | 182 | &self, |
172 | db: &dyn HirDatabase, | 183 | db: &dyn HirDatabase, |
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 82a52804d..0caedd8d8 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -473,16 +473,14 @@ impl ExprCollector<'_> { | |||
473 | self.collect_block_items(&block); | 473 | self.collect_block_items(&block); |
474 | let statements = block | 474 | let statements = block |
475 | .statements() | 475 | .statements() |
476 | .filter_map(|s| match s { | 476 | .map(|s| match s { |
477 | ast::Stmt::LetStmt(stmt) => { | 477 | ast::Stmt::LetStmt(stmt) => { |
478 | let pat = self.collect_pat_opt(stmt.pat()); | 478 | let pat = self.collect_pat_opt(stmt.pat()); |
479 | let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); | 479 | let type_ref = stmt.ascribed_type().map(TypeRef::from_ast); |
480 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); | 480 | let initializer = stmt.initializer().map(|e| self.collect_expr(e)); |
481 | Some(Statement::Let { pat, type_ref, initializer }) | 481 | Statement::Let { pat, type_ref, initializer } |
482 | } | ||
483 | ast::Stmt::ExprStmt(stmt) => { | ||
484 | Some(Statement::Expr(self.collect_expr_opt(stmt.expr()))) | ||
485 | } | 482 | } |
483 | ast::Stmt::ExprStmt(stmt) => Statement::Expr(self.collect_expr_opt(stmt.expr())), | ||
486 | }) | 484 | }) |
487 | .collect(); | 485 | .collect(); |
488 | let tail = block.expr().map(|e| self.collect_expr(e)); | 486 | let tail = block.expr().map(|e| self.collect_expr(e)); |
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs index 4d489f692..5b36a7cc1 100644 --- a/crates/ra_hir_def/src/body/scope.rs +++ b/crates/ra_hir_def/src/body/scope.rs | |||
@@ -157,6 +157,10 @@ fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope | |||
157 | for arm in arms { | 157 | for arm in arms { |
158 | let scope = scopes.new_scope(scope); | 158 | let scope = scopes.new_scope(scope); |
159 | scopes.add_bindings(body, scope, arm.pat); | 159 | scopes.add_bindings(body, scope, arm.pat); |
160 | if let Some(guard) = arm.guard { | ||
161 | scopes.set_scope(guard, scope); | ||
162 | compute_expr_scopes(guard, body, scopes, scope); | ||
163 | } | ||
160 | scopes.set_scope(arm.expr, scope); | 164 | scopes.set_scope(arm.expr, scope); |
161 | compute_expr_scopes(arm.expr, body, scopes, scope); | 165 | compute_expr_scopes(arm.expr, body, scopes, scope); |
162 | } | 166 | } |
@@ -321,8 +325,11 @@ mod tests { | |||
321 | let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); | 325 | let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); |
322 | let pat_src = source_map.pat_syntax(resolved.pat()).unwrap(); | 326 | let pat_src = source_map.pat_syntax(resolved.pat()).unwrap(); |
323 | 327 | ||
324 | let local_name = pat_src.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); | 328 | let local_name = pat_src.value.either( |
325 | assert_eq!(local_name.range(), expected_name.syntax().text_range()); | 329 | |it| it.syntax_node_ptr().to_node(file.syntax()), |
330 | |it| it.syntax_node_ptr().to_node(file.syntax()), | ||
331 | ); | ||
332 | assert_eq!(local_name.text_range(), expected_name.syntax().text_range()); | ||
326 | } | 333 | } |
327 | 334 | ||
328 | #[test] | 335 | #[test] |
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs index afd538e4a..39b011ad7 100644 --- a/crates/ra_hir_def/src/nameres/raw.rs +++ b/crates/ra_hir_def/src/nameres/raw.rs | |||
@@ -266,8 +266,8 @@ 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(_) => { | 269 | ast::ModuleItem::ExternBlock(it) => { |
270 | // FIXME: add extern block | 270 | self.add_extern_block(current_module, it); |
271 | return; | 271 | return; |
272 | } | 272 | } |
273 | }; | 273 | }; |
@@ -278,6 +278,34 @@ impl RawItemsCollector { | |||
278 | } | 278 | } |
279 | } | 279 | } |
280 | 280 | ||
281 | fn add_extern_block( | ||
282 | &mut self, | ||
283 | current_module: Option<Idx<ModuleData>>, | ||
284 | block: ast::ExternBlock, | ||
285 | ) { | ||
286 | if let Some(items) = block.extern_item_list() { | ||
287 | for item in items.extern_items() { | ||
288 | let attrs = self.parse_attrs(&item); | ||
289 | let visibility = | ||
290 | RawVisibility::from_ast_with_hygiene(item.visibility(), &self.hygiene); | ||
291 | let (kind, name) = match item { | ||
292 | ast::ExternItem::FnDef(it) => { | ||
293 | (DefKind::Function(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
294 | } | ||
295 | ast::ExternItem::StaticDef(it) => { | ||
296 | (DefKind::Static(self.source_ast_id_map.ast_id(&it)), it.name()) | ||
297 | } | ||
298 | }; | ||
299 | |||
300 | if let Some(name) = name { | ||
301 | let name = name.as_name(); | ||
302 | let def = self.raw_items.defs.alloc(DefData { name, kind, visibility }); | ||
303 | self.push_item(current_module, attrs, RawItemKind::Def(def)); | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | } | ||
308 | |||
281 | fn add_module(&mut self, current_module: Option<Idx<ModuleData>>, module: ast::Module) { | 309 | fn add_module(&mut self, current_module: Option<Idx<ModuleData>>, module: ast::Module) { |
282 | let name = match module.name() { | 310 | let name = match module.name() { |
283 | Some(it) => it.as_name(), | 311 | Some(it) => it.as_name(), |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 949ca7595..83120fa36 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -25,7 +25,7 @@ fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> { | |||
25 | #[test] | 25 | #[test] |
26 | fn crate_def_map_smoke_test() { | 26 | fn crate_def_map_smoke_test() { |
27 | let map = def_map( | 27 | let map = def_map( |
28 | " | 28 | r" |
29 | //- /lib.rs | 29 | //- /lib.rs |
30 | mod foo; | 30 | mod foo; |
31 | struct S; | 31 | struct S; |
@@ -45,6 +45,11 @@ fn crate_def_map_smoke_test() { | |||
45 | } | 45 | } |
46 | 46 | ||
47 | enum E { V } | 47 | enum E { V } |
48 | |||
49 | extern { | ||
50 | static EXT: u8; | ||
51 | fn ext(); | ||
52 | } | ||
48 | ", | 53 | ", |
49 | ); | 54 | ); |
50 | assert_snapshot!(map, @r###" | 55 | assert_snapshot!(map, @r###" |
@@ -61,7 +66,9 @@ fn crate_def_map_smoke_test() { | |||
61 | â‹®crate::foo::bar | 66 | â‹®crate::foo::bar |
62 | â‹®Baz: t v | 67 | â‹®Baz: t v |
63 | â‹®E: t | 68 | â‹®E: t |
69 | â‹®EXT: v | ||
64 | â‹®U: t v | 70 | â‹®U: t v |
71 | â‹®ext: v | ||
65 | "###) | 72 | "###) |
66 | } | 73 | } |
67 | 74 | ||
diff --git a/crates/ra_hir_expand/Cargo.toml b/crates/ra_hir_expand/Cargo.toml index d6e3c1f76..2cd522766 100644 --- a/crates/ra_hir_expand/Cargo.toml +++ b/crates/ra_hir_expand/Cargo.toml | |||
@@ -18,3 +18,4 @@ ra_parser = { path = "../ra_parser" } | |||
18 | ra_prof = { path = "../ra_prof" } | 18 | ra_prof = { path = "../ra_prof" } |
19 | tt = { path = "../ra_tt", package = "ra_tt" } | 19 | tt = { path = "../ra_tt", package = "ra_tt" } |
20 | mbe = { path = "../ra_mbe", package = "ra_mbe" } | 20 | mbe = { path = "../ra_mbe", package = "ra_mbe" } |
21 | test_utils = { path = "../test_utils"} | ||
diff --git a/crates/ra_hir_expand/src/ast_id_map.rs b/crates/ra_hir_expand/src/ast_id_map.rs index a3ca302c2..d19569245 100644 --- a/crates/ra_hir_expand/src/ast_id_map.rs +++ b/crates/ra_hir_expand/src/ast_id_map.rs | |||
@@ -66,7 +66,7 @@ impl AstIdMap { | |||
66 | // change parent's id. This means that, say, adding a new function to a | 66 | // change parent's id. This means that, say, adding a new function to a |
67 | // trait does not change ids of top-level items, which helps caching. | 67 | // trait does not change ids of top-level items, which helps caching. |
68 | bfs(node, |it| { | 68 | bfs(node, |it| { |
69 | if let Some(module_item) = ast::ModuleItem::cast(it.clone()) { | 69 | if let Some(module_item) = ast::ModuleItem::cast(it) { |
70 | res.alloc(module_item.syntax()); | 70 | res.alloc(module_item.syntax()); |
71 | } | 71 | } |
72 | }); | 72 | }); |
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs index f9d3787f6..3da137f2e 100644 --- a/crates/ra_hir_expand/src/builtin_macro.rs +++ b/crates/ra_hir_expand/src/builtin_macro.rs | |||
@@ -301,7 +301,7 @@ fn relative_file(db: &dyn AstDatabase, call_id: MacroCallId, path: &str) -> Opti | |||
301 | } | 301 | } |
302 | 302 | ||
303 | // Extern paths ? | 303 | // Extern paths ? |
304 | let krate = db.relevant_crates(call_site).get(0)?.clone(); | 304 | let krate = *db.relevant_crates(call_site).get(0)?; |
305 | let (extern_source_id, relative_file) = | 305 | let (extern_source_id, relative_file) = |
306 | db.crate_graph()[krate].extern_source.extern_path(path)?; | 306 | db.crate_graph()[krate].extern_source.extern_path(path)?; |
307 | 307 | ||
@@ -329,7 +329,7 @@ fn include_expand( | |||
329 | 329 | ||
330 | // FIXME: | 330 | // FIXME: |
331 | // Handle include as expression | 331 | // Handle include as expression |
332 | let res = parse_to_token_tree(&db.file_text(file_id.into())) | 332 | let res = parse_to_token_tree(&db.file_text(file_id)) |
333 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 333 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
334 | .0; | 334 | .0; |
335 | 335 | ||
@@ -340,7 +340,7 @@ fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Optio | |||
340 | let call_id: MacroCallId = arg_id.into(); | 340 | let call_id: MacroCallId = arg_id.into(); |
341 | let original_file = call_id.as_file().original_file(db); | 341 | let original_file = call_id.as_file().original_file(db); |
342 | 342 | ||
343 | let krate = db.relevant_crates(original_file).get(0)?.clone(); | 343 | let krate = *db.relevant_crates(original_file).get(0)?; |
344 | db.crate_graph()[krate].env.get(key) | 344 | db.crate_graph()[krate].env.get(key) |
345 | } | 345 | } |
346 | 346 | ||
@@ -447,7 +447,7 @@ mod tests { | |||
447 | file_id: file_id.into(), | 447 | file_id: file_id.into(), |
448 | }; | 448 | }; |
449 | 449 | ||
450 | let id: MacroCallId = db.intern_eager_expansion(eager.into()).into(); | 450 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); |
451 | id.as_file() | 451 | id.as_file() |
452 | } | 452 | } |
453 | }; | 453 | }; |
diff --git a/crates/ra_hir_expand/src/proc_macro.rs b/crates/ra_hir_expand/src/proc_macro.rs index 97d1208ec..4e0e069c8 100644 --- a/crates/ra_hir_expand/src/proc_macro.rs +++ b/crates/ra_hir_expand/src/proc_macro.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use crate::{db::AstDatabase, LazyMacroId}; | 3 | use crate::{db::AstDatabase, LazyMacroId}; |
4 | use ra_db::{CrateId, ProcMacroId}; | 4 | use ra_db::{CrateId, ProcMacroId}; |
5 | use tt::buffer::{Cursor, TokenBuffer}; | ||
5 | 6 | ||
6 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] | 7 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] |
7 | pub struct ProcMacroExpander { | 8 | pub struct ProcMacroExpander { |
@@ -36,22 +37,107 @@ impl ProcMacroExpander { | |||
36 | .clone() | 37 | .clone() |
37 | .ok_or_else(|| err!("No derive macro found."))?; | 38 | .ok_or_else(|| err!("No derive macro found."))?; |
38 | 39 | ||
39 | let tt = remove_derive_atr(tt, &proc_macro.name) | 40 | let tt = remove_derive_attrs(tt) |
40 | .ok_or_else(|| err!("Fail to remove derive for custom derive"))?; | 41 | .ok_or_else(|| err!("Fail to remove derive for custom derive"))?; |
41 | 42 | ||
42 | proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from) | 43 | proc_macro.expander.expand(&tt, None).map_err(mbe::ExpandError::from) |
43 | } | 44 | } |
44 | } | 45 | } |
45 | 46 | ||
46 | fn remove_derive_atr(tt: &tt::Subtree, _name: &str) -> Option<tt::Subtree> { | 47 | fn eat_punct(cursor: &mut Cursor, c: char) -> bool { |
47 | // FIXME: proper handle the remove derive | 48 | if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = cursor.token_tree() { |
48 | // We assume the first 2 tokens are #[derive(name)] | 49 | if punct.char == c { |
49 | if tt.token_trees.len() > 2 { | 50 | *cursor = cursor.bump(); |
50 | let mut tt = tt.clone(); | 51 | return true; |
51 | tt.token_trees.remove(0); | 52 | } |
52 | tt.token_trees.remove(0); | ||
53 | return Some(tt); | ||
54 | } | 53 | } |
54 | false | ||
55 | } | ||
56 | |||
57 | fn eat_subtree(cursor: &mut Cursor, kind: tt::DelimiterKind) -> bool { | ||
58 | if let Some(tt::TokenTree::Subtree(subtree)) = cursor.token_tree() { | ||
59 | if Some(kind) == subtree.delimiter_kind() { | ||
60 | *cursor = cursor.bump_subtree(); | ||
61 | return true; | ||
62 | } | ||
63 | } | ||
64 | false | ||
65 | } | ||
66 | |||
67 | fn eat_ident(cursor: &mut Cursor, t: &str) -> bool { | ||
68 | if let Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) = cursor.token_tree() { | ||
69 | if t == ident.text.as_str() { | ||
70 | *cursor = cursor.bump(); | ||
71 | return true; | ||
72 | } | ||
73 | } | ||
74 | false | ||
75 | } | ||
76 | |||
77 | fn remove_derive_attrs(tt: &tt::Subtree) -> Option<tt::Subtree> { | ||
78 | let buffer = TokenBuffer::new(&tt.token_trees); | ||
79 | let mut p = buffer.begin(); | ||
80 | let mut result = tt::Subtree::default(); | ||
81 | |||
82 | while !p.eof() { | ||
83 | let curr = p; | ||
55 | 84 | ||
56 | None | 85 | if eat_punct(&mut p, '#') { |
86 | eat_punct(&mut p, '!'); | ||
87 | let parent = p; | ||
88 | if eat_subtree(&mut p, tt::DelimiterKind::Bracket) { | ||
89 | if eat_ident(&mut p, "derive") { | ||
90 | p = parent.bump(); | ||
91 | continue; | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
96 | result.token_trees.push(curr.token_tree()?.clone()); | ||
97 | p = curr.bump(); | ||
98 | } | ||
99 | |||
100 | Some(result) | ||
101 | } | ||
102 | |||
103 | #[cfg(test)] | ||
104 | mod test { | ||
105 | use super::*; | ||
106 | use test_utils::assert_eq_text; | ||
107 | |||
108 | #[test] | ||
109 | fn test_remove_derive_attrs() { | ||
110 | let tt = mbe::parse_to_token_tree( | ||
111 | r#" | ||
112 | #[allow(unused)] | ||
113 | #[derive(Copy)] | ||
114 | #[derive(Hello)] | ||
115 | struct A { | ||
116 | bar: u32 | ||
117 | } | ||
118 | "#, | ||
119 | ) | ||
120 | .unwrap() | ||
121 | .0; | ||
122 | let result = format!("{:#?}", remove_derive_attrs(&tt).unwrap()); | ||
123 | |||
124 | assert_eq_text!( | ||
125 | &result, | ||
126 | r#" | ||
127 | SUBTREE $ | ||
128 | PUNCH # [alone] 0 | ||
129 | SUBTREE [] 1 | ||
130 | IDENT allow 2 | ||
131 | SUBTREE () 3 | ||
132 | IDENT unused 4 | ||
133 | IDENT struct 15 | ||
134 | IDENT A 16 | ||
135 | SUBTREE {} 17 | ||
136 | IDENT bar 18 | ||
137 | PUNCH : [alone] 19 | ||
138 | IDENT u32 20 | ||
139 | "# | ||
140 | .trim() | ||
141 | ); | ||
142 | } | ||
57 | } | 143 | } |
diff --git a/crates/ra_hir_ty/Cargo.toml b/crates/ra_hir_ty/Cargo.toml index 177bdbcb0..04d3cd6a2 100644 --- a/crates/ra_hir_ty/Cargo.toml +++ b/crates/ra_hir_ty/Cargo.toml | |||
@@ -27,9 +27,9 @@ test_utils = { path = "../test_utils" } | |||
27 | 27 | ||
28 | scoped-tls = "1" | 28 | scoped-tls = "1" |
29 | 29 | ||
30 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "28cef6ff403d403e6ad2f3d27d944e9ffac1bce8" } | 30 | chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" } |
31 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "28cef6ff403d403e6ad2f3d27d944e9ffac1bce8" } | 31 | chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" } |
32 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "28cef6ff403d403e6ad2f3d27d944e9ffac1bce8" } | 32 | chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" } |
33 | 33 | ||
34 | [dev-dependencies] | 34 | [dev-dependencies] |
35 | insta = "0.16.0" | 35 | insta = "0.16.0" |
diff --git a/crates/ra_hir_ty/src/_match.rs b/crates/ra_hir_ty/src/_match.rs index 688026a04..779e78574 100644 --- a/crates/ra_hir_ty/src/_match.rs +++ b/crates/ra_hir_ty/src/_match.rs | |||
@@ -235,10 +235,19 @@ impl From<PatId> for PatIdOrWild { | |||
235 | } | 235 | } |
236 | } | 236 | } |
237 | 237 | ||
238 | impl From<&PatId> for PatIdOrWild { | ||
239 | fn from(pat_id: &PatId) -> Self { | ||
240 | Self::PatId(*pat_id) | ||
241 | } | ||
242 | } | ||
243 | |||
238 | #[derive(Debug, Clone, Copy, PartialEq)] | 244 | #[derive(Debug, Clone, Copy, PartialEq)] |
239 | pub enum MatchCheckErr { | 245 | pub enum MatchCheckErr { |
240 | NotImplemented, | 246 | NotImplemented, |
241 | MalformedMatchArm, | 247 | MalformedMatchArm, |
248 | /// Used when type inference cannot resolve the type of | ||
249 | /// a pattern or expression. | ||
250 | Unknown, | ||
242 | } | 251 | } |
243 | 252 | ||
244 | /// The return type of `is_useful` is either an indication of usefulness | 253 | /// The return type of `is_useful` is either an indication of usefulness |
@@ -290,10 +299,14 @@ impl PatStack { | |||
290 | Self::from_slice(&self.0[1..]) | 299 | Self::from_slice(&self.0[1..]) |
291 | } | 300 | } |
292 | 301 | ||
293 | fn replace_head_with<T: Into<PatIdOrWild> + Copy>(&self, pat_ids: &[T]) -> PatStack { | 302 | fn replace_head_with<I, T>(&self, pats: I) -> PatStack |
303 | where | ||
304 | I: Iterator<Item = T>, | ||
305 | T: Into<PatIdOrWild>, | ||
306 | { | ||
294 | let mut patterns: PatStackInner = smallvec![]; | 307 | let mut patterns: PatStackInner = smallvec![]; |
295 | for pat in pat_ids { | 308 | for pat in pats { |
296 | patterns.push((*pat).into()); | 309 | patterns.push(pat.into()); |
297 | } | 310 | } |
298 | for pat in &self.0[1..] { | 311 | for pat in &self.0[1..] { |
299 | patterns.push(*pat); | 312 | patterns.push(*pat); |
@@ -330,7 +343,7 @@ impl PatStack { | |||
330 | return Err(MatchCheckErr::NotImplemented); | 343 | return Err(MatchCheckErr::NotImplemented); |
331 | } | 344 | } |
332 | 345 | ||
333 | Some(self.replace_head_with(pat_ids)) | 346 | Some(self.replace_head_with(pat_ids.iter())) |
334 | } | 347 | } |
335 | (Pat::Lit(lit_expr), Constructor::Bool(constructor_val)) => { | 348 | (Pat::Lit(lit_expr), Constructor::Bool(constructor_val)) => { |
336 | match cx.body.exprs[lit_expr] { | 349 | match cx.body.exprs[lit_expr] { |
@@ -382,7 +395,7 @@ impl PatStack { | |||
382 | new_patterns.push((*pat_id).into()); | 395 | new_patterns.push((*pat_id).into()); |
383 | } | 396 | } |
384 | 397 | ||
385 | Some(self.replace_head_with(&new_patterns)) | 398 | Some(self.replace_head_with(new_patterns.into_iter())) |
386 | } else { | 399 | } else { |
387 | return Err(MatchCheckErr::MalformedMatchArm); | 400 | return Err(MatchCheckErr::MalformedMatchArm); |
388 | } | 401 | } |
@@ -390,13 +403,41 @@ impl PatStack { | |||
390 | // If there is no ellipsis in the tuple pattern, the number | 403 | // If there is no ellipsis in the tuple pattern, the number |
391 | // of patterns must equal the constructor arity. | 404 | // of patterns must equal the constructor arity. |
392 | if pat_ids.len() == constructor_arity { | 405 | if pat_ids.len() == constructor_arity { |
393 | Some(self.replace_head_with(pat_ids)) | 406 | Some(self.replace_head_with(pat_ids.into_iter())) |
394 | } else { | 407 | } else { |
395 | return Err(MatchCheckErr::MalformedMatchArm); | 408 | return Err(MatchCheckErr::MalformedMatchArm); |
396 | } | 409 | } |
397 | } | 410 | } |
398 | } | 411 | } |
399 | } | 412 | } |
413 | (Pat::Record { args: ref arg_patterns, .. }, Constructor::Enum(e)) => { | ||
414 | let pat_id = self.head().as_id().expect("we know this isn't a wild"); | ||
415 | if !enum_variant_matches(cx, pat_id, *e) { | ||
416 | None | ||
417 | } else { | ||
418 | match cx.db.enum_data(e.parent).variants[e.local_id].variant_data.as_ref() { | ||
419 | VariantData::Record(struct_field_arena) => { | ||
420 | // Here we treat any missing fields in the record as the wild pattern, as | ||
421 | // if the record has ellipsis. We want to do this here even if the | ||
422 | // record does not contain ellipsis, because it allows us to continue | ||
423 | // enforcing exhaustiveness for the rest of the match statement. | ||
424 | // | ||
425 | // Creating the diagnostic for the missing field in the pattern | ||
426 | // should be done in a different diagnostic. | ||
427 | let patterns = struct_field_arena.iter().map(|(_, struct_field)| { | ||
428 | arg_patterns | ||
429 | .iter() | ||
430 | .find(|pat| pat.name == struct_field.name) | ||
431 | .map(|pat| PatIdOrWild::from(pat.pat)) | ||
432 | .unwrap_or(PatIdOrWild::Wild) | ||
433 | }); | ||
434 | |||
435 | Some(self.replace_head_with(patterns)) | ||
436 | } | ||
437 | _ => return Err(MatchCheckErr::Unknown), | ||
438 | } | ||
439 | } | ||
440 | } | ||
400 | (Pat::Or(_), _) => return Err(MatchCheckErr::NotImplemented), | 441 | (Pat::Or(_), _) => return Err(MatchCheckErr::NotImplemented), |
401 | (_, _) => return Err(MatchCheckErr::NotImplemented), | 442 | (_, _) => return Err(MatchCheckErr::NotImplemented), |
402 | }; | 443 | }; |
@@ -655,8 +696,8 @@ impl Constructor { | |||
655 | Constructor::Enum(e) => { | 696 | Constructor::Enum(e) => { |
656 | match cx.db.enum_data(e.parent).variants[e.local_id].variant_data.as_ref() { | 697 | match cx.db.enum_data(e.parent).variants[e.local_id].variant_data.as_ref() { |
657 | VariantData::Tuple(struct_field_data) => struct_field_data.len(), | 698 | VariantData::Tuple(struct_field_data) => struct_field_data.len(), |
699 | VariantData::Record(struct_field_data) => struct_field_data.len(), | ||
658 | VariantData::Unit => 0, | 700 | VariantData::Unit => 0, |
659 | _ => return Err(MatchCheckErr::NotImplemented), | ||
660 | } | 701 | } |
661 | } | 702 | } |
662 | }; | 703 | }; |
@@ -695,10 +736,10 @@ fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult<Opt | |||
695 | Expr::Literal(Literal::Bool(val)) => Some(Constructor::Bool(val)), | 736 | Expr::Literal(Literal::Bool(val)) => Some(Constructor::Bool(val)), |
696 | _ => return Err(MatchCheckErr::NotImplemented), | 737 | _ => return Err(MatchCheckErr::NotImplemented), |
697 | }, | 738 | }, |
698 | Pat::TupleStruct { .. } | Pat::Path(_) => { | 739 | Pat::TupleStruct { .. } | Pat::Path(_) | Pat::Record { .. } => { |
699 | let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); | 740 | let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); |
700 | let variant_id = | 741 | let variant_id = |
701 | cx.infer.variant_resolution_for_pat(pat_id).ok_or(MatchCheckErr::NotImplemented)?; | 742 | cx.infer.variant_resolution_for_pat(pat_id).ok_or(MatchCheckErr::Unknown)?; |
702 | match variant_id { | 743 | match variant_id { |
703 | VariantId::EnumVariantId(enum_variant_id) => { | 744 | VariantId::EnumVariantId(enum_variant_id) => { |
704 | Some(Constructor::Enum(enum_variant_id)) | 745 | Some(Constructor::Enum(enum_variant_id)) |
@@ -759,20 +800,22 @@ mod tests { | |||
759 | pub(super) use insta::assert_snapshot; | 800 | pub(super) use insta::assert_snapshot; |
760 | pub(super) use ra_db::fixture::WithFixture; | 801 | pub(super) use ra_db::fixture::WithFixture; |
761 | 802 | ||
762 | pub(super) use crate::test_db::TestDB; | 803 | pub(super) use crate::{diagnostics::MissingMatchArms, test_db::TestDB}; |
763 | 804 | ||
764 | pub(super) fn check_diagnostic_message(content: &str) -> String { | 805 | pub(super) fn check_diagnostic_message(content: &str) -> String { |
765 | TestDB::with_single_file(content).0.diagnostics().0 | 806 | TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().0 |
766 | } | 807 | } |
767 | 808 | ||
768 | pub(super) fn check_diagnostic(content: &str) { | 809 | pub(super) fn check_diagnostic(content: &str) { |
769 | let diagnostic_count = TestDB::with_single_file(content).0.diagnostics().1; | 810 | let diagnostic_count = |
811 | TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().1; | ||
770 | 812 | ||
771 | assert_eq!(1, diagnostic_count, "no diagnostic reported"); | 813 | assert_eq!(1, diagnostic_count, "no diagnostic reported"); |
772 | } | 814 | } |
773 | 815 | ||
774 | pub(super) fn check_no_diagnostic(content: &str) { | 816 | pub(super) fn check_no_diagnostic(content: &str) { |
775 | let diagnostic_count = TestDB::with_single_file(content).0.diagnostics().1; | 817 | let diagnostic_count = |
818 | TestDB::with_single_file(content).0.diagnostic::<MissingMatchArms>().1; | ||
776 | 819 | ||
777 | assert_eq!(0, diagnostic_count, "expected no diagnostic, found one"); | 820 | assert_eq!(0, diagnostic_count, "expected no diagnostic, found one"); |
778 | } | 821 | } |
@@ -1532,6 +1575,236 @@ mod tests { | |||
1532 | } | 1575 | } |
1533 | 1576 | ||
1534 | #[test] | 1577 | #[test] |
1578 | fn enum_record_no_arms() { | ||
1579 | let content = r" | ||
1580 | enum Either { | ||
1581 | A { foo: bool }, | ||
1582 | B, | ||
1583 | } | ||
1584 | fn test_fn() { | ||
1585 | let a = Either::A { foo: true }; | ||
1586 | match a { | ||
1587 | } | ||
1588 | } | ||
1589 | "; | ||
1590 | |||
1591 | check_diagnostic(content); | ||
1592 | } | ||
1593 | |||
1594 | #[test] | ||
1595 | fn enum_record_missing_arms() { | ||
1596 | let content = r" | ||
1597 | enum Either { | ||
1598 | A { foo: bool }, | ||
1599 | B, | ||
1600 | } | ||
1601 | fn test_fn() { | ||
1602 | let a = Either::A { foo: true }; | ||
1603 | match a { | ||
1604 | Either::A { foo: true } => (), | ||
1605 | } | ||
1606 | } | ||
1607 | "; | ||
1608 | |||
1609 | check_diagnostic(content); | ||
1610 | } | ||
1611 | |||
1612 | #[test] | ||
1613 | fn enum_record_no_diagnostic() { | ||
1614 | let content = r" | ||
1615 | enum Either { | ||
1616 | A { foo: bool }, | ||
1617 | B, | ||
1618 | } | ||
1619 | fn test_fn() { | ||
1620 | let a = Either::A { foo: true }; | ||
1621 | match a { | ||
1622 | Either::A { foo: true } => (), | ||
1623 | Either::A { foo: false } => (), | ||
1624 | Either::B => (), | ||
1625 | } | ||
1626 | } | ||
1627 | "; | ||
1628 | |||
1629 | check_no_diagnostic(content); | ||
1630 | } | ||
1631 | |||
1632 | #[test] | ||
1633 | fn enum_record_missing_field_no_diagnostic() { | ||
1634 | let content = r" | ||
1635 | enum Either { | ||
1636 | A { foo: bool }, | ||
1637 | B, | ||
1638 | } | ||
1639 | fn test_fn() { | ||
1640 | let a = Either::B; | ||
1641 | match a { | ||
1642 | Either::A { } => (), | ||
1643 | Either::B => (), | ||
1644 | } | ||
1645 | } | ||
1646 | "; | ||
1647 | |||
1648 | // When `Either::A` is missing a struct member, we don't want | ||
1649 | // to fire the missing match arm diagnostic. This should fire | ||
1650 | // some other diagnostic. | ||
1651 | check_no_diagnostic(content); | ||
1652 | } | ||
1653 | |||
1654 | #[test] | ||
1655 | fn enum_record_missing_field_missing_match_arm() { | ||
1656 | let content = r" | ||
1657 | enum Either { | ||
1658 | A { foo: bool }, | ||
1659 | B, | ||
1660 | } | ||
1661 | fn test_fn() { | ||
1662 | let a = Either::B; | ||
1663 | match a { | ||
1664 | Either::A { } => (), | ||
1665 | } | ||
1666 | } | ||
1667 | "; | ||
1668 | |||
1669 | // Even though `Either::A` is missing fields, we still want to fire | ||
1670 | // the missing arm diagnostic here, since we know `Either::B` is missing. | ||
1671 | check_diagnostic(content); | ||
1672 | } | ||
1673 | |||
1674 | #[test] | ||
1675 | fn enum_record_no_diagnostic_wild() { | ||
1676 | let content = r" | ||
1677 | enum Either { | ||
1678 | A { foo: bool }, | ||
1679 | B, | ||
1680 | } | ||
1681 | fn test_fn() { | ||
1682 | let a = Either::A { foo: true }; | ||
1683 | match a { | ||
1684 | Either::A { foo: _ } => (), | ||
1685 | Either::B => (), | ||
1686 | } | ||
1687 | } | ||
1688 | "; | ||
1689 | |||
1690 | check_no_diagnostic(content); | ||
1691 | } | ||
1692 | |||
1693 | #[test] | ||
1694 | fn enum_record_fields_out_of_order_missing_arm() { | ||
1695 | let content = r" | ||
1696 | enum Either { | ||
1697 | A { foo: bool, bar: () }, | ||
1698 | B, | ||
1699 | } | ||
1700 | fn test_fn() { | ||
1701 | let a = Either::A { foo: true }; | ||
1702 | match a { | ||
1703 | Either::A { bar: (), foo: false } => (), | ||
1704 | Either::A { foo: true, bar: () } => (), | ||
1705 | } | ||
1706 | } | ||
1707 | "; | ||
1708 | |||
1709 | check_diagnostic(content); | ||
1710 | } | ||
1711 | |||
1712 | #[test] | ||
1713 | fn enum_record_fields_out_of_order_no_diagnostic() { | ||
1714 | let content = r" | ||
1715 | enum Either { | ||
1716 | A { foo: bool, bar: () }, | ||
1717 | B, | ||
1718 | } | ||
1719 | fn test_fn() { | ||
1720 | let a = Either::A { foo: true }; | ||
1721 | match a { | ||
1722 | Either::A { bar: (), foo: false } => (), | ||
1723 | Either::A { foo: true, bar: () } => (), | ||
1724 | Either::B => (), | ||
1725 | } | ||
1726 | } | ||
1727 | "; | ||
1728 | |||
1729 | check_no_diagnostic(content); | ||
1730 | } | ||
1731 | |||
1732 | #[test] | ||
1733 | fn enum_record_ellipsis_missing_arm() { | ||
1734 | let content = r" | ||
1735 | enum Either { | ||
1736 | A { foo: bool, bar: bool }, | ||
1737 | B, | ||
1738 | } | ||
1739 | fn test_fn() { | ||
1740 | match Either::B { | ||
1741 | Either::A { foo: true, .. } => (), | ||
1742 | Either::B => (), | ||
1743 | } | ||
1744 | } | ||
1745 | "; | ||
1746 | |||
1747 | check_diagnostic(content); | ||
1748 | } | ||
1749 | |||
1750 | #[test] | ||
1751 | fn enum_record_ellipsis_no_diagnostic() { | ||
1752 | let content = r" | ||
1753 | enum Either { | ||
1754 | A { foo: bool, bar: bool }, | ||
1755 | B, | ||
1756 | } | ||
1757 | fn test_fn() { | ||
1758 | let a = Either::A { foo: true }; | ||
1759 | match a { | ||
1760 | Either::A { foo: true, .. } => (), | ||
1761 | Either::A { foo: false, .. } => (), | ||
1762 | Either::B => (), | ||
1763 | } | ||
1764 | } | ||
1765 | "; | ||
1766 | |||
1767 | check_no_diagnostic(content); | ||
1768 | } | ||
1769 | |||
1770 | #[test] | ||
1771 | fn enum_record_ellipsis_all_fields_missing_arm() { | ||
1772 | let content = r" | ||
1773 | enum Either { | ||
1774 | A { foo: bool, bar: bool }, | ||
1775 | B, | ||
1776 | } | ||
1777 | fn test_fn() { | ||
1778 | let a = Either::B; | ||
1779 | match a { | ||
1780 | Either::A { .. } => (), | ||
1781 | } | ||
1782 | } | ||
1783 | "; | ||
1784 | |||
1785 | check_diagnostic(content); | ||
1786 | } | ||
1787 | |||
1788 | #[test] | ||
1789 | fn enum_record_ellipsis_all_fields_no_diagnostic() { | ||
1790 | let content = r" | ||
1791 | enum Either { | ||
1792 | A { foo: bool, bar: bool }, | ||
1793 | B, | ||
1794 | } | ||
1795 | fn test_fn() { | ||
1796 | let a = Either::B; | ||
1797 | match a { | ||
1798 | Either::A { .. } => (), | ||
1799 | Either::B => (), | ||
1800 | } | ||
1801 | } | ||
1802 | "; | ||
1803 | |||
1804 | check_no_diagnostic(content); | ||
1805 | } | ||
1806 | |||
1807 | #[test] | ||
1535 | fn enum_tuple_partial_ellipsis_no_diagnostic() { | 1808 | fn enum_tuple_partial_ellipsis_no_diagnostic() { |
1536 | let content = r" | 1809 | let content = r" |
1537 | enum Either { | 1810 | enum Either { |
@@ -1689,25 +1962,6 @@ mod false_negatives { | |||
1689 | } | 1962 | } |
1690 | 1963 | ||
1691 | #[test] | 1964 | #[test] |
1692 | fn enum_record() { | ||
1693 | let content = r" | ||
1694 | enum Either { | ||
1695 | A { foo: u32 }, | ||
1696 | B, | ||
1697 | } | ||
1698 | fn test_fn() { | ||
1699 | match Either::B { | ||
1700 | Either::A { foo: 5 } => (), | ||
1701 | } | ||
1702 | } | ||
1703 | "; | ||
1704 | |||
1705 | // This is a false negative. | ||
1706 | // We don't currently handle enum record types. | ||
1707 | check_no_diagnostic(content); | ||
1708 | } | ||
1709 | |||
1710 | #[test] | ||
1711 | fn internal_or() { | 1965 | fn internal_or() { |
1712 | let content = r" | 1966 | let content = r" |
1713 | fn test_fn() { | 1967 | fn test_fn() { |
@@ -1796,4 +2050,22 @@ mod false_negatives { | |||
1796 | // We don't currently handle tuple patterns with ellipsis. | 2050 | // We don't currently handle tuple patterns with ellipsis. |
1797 | check_no_diagnostic(content); | 2051 | check_no_diagnostic(content); |
1798 | } | 2052 | } |
2053 | |||
2054 | #[test] | ||
2055 | fn struct_missing_arm() { | ||
2056 | let content = r" | ||
2057 | struct Foo { | ||
2058 | a: bool, | ||
2059 | } | ||
2060 | fn test_fn(f: Foo) { | ||
2061 | match f { | ||
2062 | Foo { a: true } => {}, | ||
2063 | } | ||
2064 | } | ||
2065 | "; | ||
2066 | |||
2067 | // This is a false negative. | ||
2068 | // We don't currently handle structs. | ||
2069 | check_no_diagnostic(content); | ||
2070 | } | ||
1799 | } | 2071 | } |
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index 33da16b48..9e5dfeab3 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -107,6 +107,13 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
107 | krate: CrateId, | 107 | krate: CrateId, |
108 | goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>, | 108 | goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>, |
109 | ) -> Option<crate::traits::Solution>; | 109 | ) -> Option<crate::traits::Solution>; |
110 | |||
111 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] | ||
112 | fn program_clauses_for_chalk_env( | ||
113 | &self, | ||
114 | krate: CrateId, | ||
115 | env: chalk_ir::Environment<chalk::Interner>, | ||
116 | ) -> chalk_ir::ProgramClauses<chalk::Interner>; | ||
110 | } | 117 | } |
111 | 118 | ||
112 | fn infer_wait(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { | 119 | fn infer_wait(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index b6d9b3438..dfb6a435f 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -127,6 +127,7 @@ pub struct InferenceResult { | |||
127 | field_resolutions: FxHashMap<ExprId, StructFieldId>, | 127 | field_resolutions: FxHashMap<ExprId, StructFieldId>, |
128 | /// For each field in record literal, records the field it resolves to. | 128 | /// For each field in record literal, records the field it resolves to. |
129 | record_field_resolutions: FxHashMap<ExprId, StructFieldId>, | 129 | record_field_resolutions: FxHashMap<ExprId, StructFieldId>, |
130 | record_field_pat_resolutions: FxHashMap<PatId, StructFieldId>, | ||
130 | /// For each struct literal, records the variant it resolves to. | 131 | /// For each struct literal, records the variant it resolves to. |
131 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, | 132 | variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, |
132 | /// For each associated item record what it resolves to | 133 | /// For each associated item record what it resolves to |
@@ -147,6 +148,9 @@ impl InferenceResult { | |||
147 | pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructFieldId> { | 148 | pub fn record_field_resolution(&self, expr: ExprId) -> Option<StructFieldId> { |
148 | self.record_field_resolutions.get(&expr).copied() | 149 | self.record_field_resolutions.get(&expr).copied() |
149 | } | 150 | } |
151 | pub fn record_field_pat_resolution(&self, pat: PatId) -> Option<StructFieldId> { | ||
152 | self.record_field_pat_resolutions.get(&pat).copied() | ||
153 | } | ||
150 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { | 154 | pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { |
151 | self.variant_resolutions.get(&id.into()).copied() | 155 | self.variant_resolutions.get(&id.into()).copied() |
152 | } | 156 | } |
diff --git a/crates/ra_hir_ty/src/infer/pat.rs b/crates/ra_hir_ty/src/infer/pat.rs index 8ec4d4ace..7c2ad4384 100644 --- a/crates/ra_hir_ty/src/infer/pat.rs +++ b/crates/ra_hir_ty/src/infer/pat.rs | |||
@@ -7,6 +7,7 @@ use hir_def::{ | |||
7 | expr::{BindingAnnotation, Pat, PatId, RecordFieldPat}, | 7 | expr::{BindingAnnotation, Pat, PatId, RecordFieldPat}, |
8 | path::Path, | 8 | path::Path, |
9 | type_ref::Mutability, | 9 | type_ref::Mutability, |
10 | StructFieldId, | ||
10 | }; | 11 | }; |
11 | use hir_expand::name::Name; | 12 | use hir_expand::name::Name; |
12 | use test_utils::tested_by; | 13 | use test_utils::tested_by; |
@@ -67,6 +68,11 @@ impl<'a> InferenceContext<'a> { | |||
67 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 68 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
68 | for subpat in subpats { | 69 | for subpat in subpats { |
69 | let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); | 70 | let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); |
71 | if let Some(local_id) = matching_field { | ||
72 | let field_def = StructFieldId { parent: def.unwrap(), local_id }; | ||
73 | self.result.record_field_pat_resolutions.insert(subpat.pat, field_def); | ||
74 | } | ||
75 | |||
70 | let expected_ty = | 76 | let expected_ty = |
71 | matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); | 77 | matching_field.map_or(Ty::Unknown, |field| field_tys[field].clone().subst(&substs)); |
72 | let expected_ty = self.normalize_associated_types_in(expected_ty); | 78 | let expected_ty = self.normalize_associated_types_in(expected_ty); |
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs index a4b8d6683..279c06d65 100644 --- a/crates/ra_hir_ty/src/lib.rs +++ b/crates/ra_hir_ty/src/lib.rs | |||
@@ -863,7 +863,7 @@ pub trait TypeWalk { | |||
863 | &mut |ty, binders| { | 863 | &mut |ty, binders| { |
864 | if let &mut Ty::Bound(bound) = ty { | 864 | if let &mut Ty::Bound(bound) = ty { |
865 | if bound.debruijn >= binders { | 865 | if bound.debruijn >= binders { |
866 | *ty = substs.0[bound.index].clone(); | 866 | *ty = substs.0[bound.index].clone().shift_bound_vars(binders); |
867 | } | 867 | } |
868 | } | 868 | } |
869 | }, | 869 | }, |
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs index 3a4d58bf9..8498d3d96 100644 --- a/crates/ra_hir_ty/src/test_db.rs +++ b/crates/ra_hir_ty/src/test_db.rs | |||
@@ -12,7 +12,7 @@ use ra_db::{ | |||
12 | }; | 12 | }; |
13 | use stdx::format_to; | 13 | use stdx::format_to; |
14 | 14 | ||
15 | use crate::{db::HirDatabase, expr::ExprValidator}; | 15 | use crate::{db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator}; |
16 | 16 | ||
17 | #[salsa::database( | 17 | #[salsa::database( |
18 | ra_db::SourceDatabaseExtStorage, | 18 | ra_db::SourceDatabaseExtStorage, |
@@ -104,10 +104,7 @@ impl TestDB { | |||
104 | panic!("Can't find module for file") | 104 | panic!("Can't find module for file") |
105 | } | 105 | } |
106 | 106 | ||
107 | // FIXME: don't duplicate this | 107 | fn diag<F: FnMut(&dyn Diagnostic)>(&self, mut cb: F) { |
108 | pub fn diagnostics(&self) -> (String, u32) { | ||
109 | let mut buf = String::new(); | ||
110 | let mut count = 0; | ||
111 | let crate_graph = self.crate_graph(); | 108 | let crate_graph = self.crate_graph(); |
112 | for krate in crate_graph.iter() { | 109 | for krate in crate_graph.iter() { |
113 | let crate_def_map = self.crate_def_map(krate); | 110 | let crate_def_map = self.crate_def_map(krate); |
@@ -132,15 +129,36 @@ impl TestDB { | |||
132 | 129 | ||
133 | for f in fns { | 130 | for f in fns { |
134 | let infer = self.infer(f.into()); | 131 | let infer = self.infer(f.into()); |
135 | let mut sink = DiagnosticSink::new(|d| { | 132 | let mut sink = DiagnosticSink::new(&mut cb); |
136 | format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message()); | ||
137 | count += 1; | ||
138 | }); | ||
139 | infer.add_diagnostics(self, f, &mut sink); | 133 | infer.add_diagnostics(self, f, &mut sink); |
140 | let mut validator = ExprValidator::new(f, infer, &mut sink); | 134 | let mut validator = ExprValidator::new(f, infer, &mut sink); |
141 | validator.validate_body(self); | 135 | validator.validate_body(self); |
142 | } | 136 | } |
143 | } | 137 | } |
138 | } | ||
139 | |||
140 | pub fn diagnostics(&self) -> (String, u32) { | ||
141 | let mut buf = String::new(); | ||
142 | let mut count = 0; | ||
143 | self.diag(|d| { | ||
144 | format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message()); | ||
145 | count += 1; | ||
146 | }); | ||
147 | (buf, count) | ||
148 | } | ||
149 | |||
150 | /// Like `diagnostics`, but filtered for a single diagnostic. | ||
151 | pub fn diagnostic<D: Diagnostic>(&self) -> (String, u32) { | ||
152 | let mut buf = String::new(); | ||
153 | let mut count = 0; | ||
154 | self.diag(|d| { | ||
155 | // We want to filter diagnostics by the particular one we are testing for, to | ||
156 | // avoid surprising results in tests. | ||
157 | if d.downcast_ref::<D>().is_some() { | ||
158 | format_to!(buf, "{:?}: {}\n", d.syntax_node(self).text(), d.message()); | ||
159 | count += 1; | ||
160 | }; | ||
161 | }); | ||
144 | (buf, count) | 162 | (buf, count) |
145 | } | 163 | } |
146 | } | 164 | } |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 81fc0f63a..846005baa 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -18,16 +18,19 @@ use hir_def::{ | |||
18 | nameres::CrateDefMap, | 18 | nameres::CrateDefMap, |
19 | AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, | 19 | AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, |
20 | }; | 20 | }; |
21 | use hir_expand::InFile; | 21 | use hir_expand::{db::AstDatabase, InFile}; |
22 | use insta::assert_snapshot; | 22 | use insta::assert_snapshot; |
23 | use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; | 23 | use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; |
24 | use ra_syntax::{ | 24 | use ra_syntax::{ |
25 | algo, | 25 | algo, |
26 | ast::{self, AstNode}, | 26 | ast::{self, AstNode}, |
27 | SyntaxNode, | ||
27 | }; | 28 | }; |
28 | use stdx::format_to; | 29 | use stdx::format_to; |
29 | 30 | ||
30 | use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult}; | 31 | use crate::{ |
32 | db::HirDatabase, display::HirDisplay, infer::TypeMismatch, test_db::TestDB, InferenceResult, Ty, | ||
33 | }; | ||
31 | 34 | ||
32 | // These tests compare the inference results for all expressions in a file | 35 | // These tests compare the inference results for all expressions in a file |
33 | // against snapshots of the expected results using insta. Use cargo-insta to | 36 | // against snapshots of the expected results using insta. Use cargo-insta to |
@@ -67,13 +70,19 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
67 | 70 | ||
68 | let mut infer_def = |inference_result: Arc<InferenceResult>, | 71 | let mut infer_def = |inference_result: Arc<InferenceResult>, |
69 | body_source_map: Arc<BodySourceMap>| { | 72 | body_source_map: Arc<BodySourceMap>| { |
70 | let mut types = Vec::new(); | 73 | let mut types: Vec<(InFile<SyntaxNode>, &Ty)> = Vec::new(); |
71 | let mut mismatches = Vec::new(); | 74 | let mut mismatches: Vec<(InFile<SyntaxNode>, &TypeMismatch)> = Vec::new(); |
72 | 75 | ||
73 | for (pat, ty) in inference_result.type_of_pat.iter() { | 76 | for (pat, ty) in inference_result.type_of_pat.iter() { |
74 | let syntax_ptr = match body_source_map.pat_syntax(pat) { | 77 | let syntax_ptr = match body_source_map.pat_syntax(pat) { |
75 | Ok(sp) => { | 78 | Ok(sp) => { |
76 | sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr())) | 79 | let root = db.parse_or_expand(sp.file_id).unwrap(); |
80 | sp.map(|ptr| { | ||
81 | ptr.either( | ||
82 | |it| it.to_node(&root).syntax().clone(), | ||
83 | |it| it.to_node(&root).syntax().clone(), | ||
84 | ) | ||
85 | }) | ||
77 | } | 86 | } |
78 | Err(SyntheticSyntax) => continue, | 87 | Err(SyntheticSyntax) => continue, |
79 | }; | 88 | }; |
@@ -81,29 +90,31 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
81 | } | 90 | } |
82 | 91 | ||
83 | for (expr, ty) in inference_result.type_of_expr.iter() { | 92 | for (expr, ty) in inference_result.type_of_expr.iter() { |
84 | let syntax_ptr = match body_source_map.expr_syntax(expr) { | 93 | let node = match body_source_map.expr_syntax(expr) { |
85 | Ok(sp) => sp.map(|ast| ast.syntax_node_ptr()), | 94 | Ok(sp) => { |
95 | let root = db.parse_or_expand(sp.file_id).unwrap(); | ||
96 | sp.map(|ptr| ptr.to_node(&root).syntax().clone()) | ||
97 | } | ||
86 | Err(SyntheticSyntax) => continue, | 98 | Err(SyntheticSyntax) => continue, |
87 | }; | 99 | }; |
88 | types.push((syntax_ptr.clone(), ty)); | 100 | types.push((node.clone(), ty)); |
89 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { | 101 | if let Some(mismatch) = inference_result.type_mismatch_for_expr(expr) { |
90 | mismatches.push((syntax_ptr, mismatch)); | 102 | mismatches.push((node, mismatch)); |
91 | } | 103 | } |
92 | } | 104 | } |
93 | 105 | ||
94 | // sort ranges for consistency | 106 | // sort ranges for consistency |
95 | types.sort_by_key(|(src_ptr, _)| { | 107 | types.sort_by_key(|(node, _)| { |
96 | (src_ptr.value.range().start(), src_ptr.value.range().end()) | 108 | let range = node.value.text_range(); |
109 | (range.start(), range.end()) | ||
97 | }); | 110 | }); |
98 | for (src_ptr, ty) in &types { | 111 | for (node, ty) in &types { |
99 | let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db)); | 112 | let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.value.clone()) { |
100 | |||
101 | let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { | ||
102 | (self_param.self_token().unwrap().text_range(), "self".to_string()) | 113 | (self_param.self_token().unwrap().text_range(), "self".to_string()) |
103 | } else { | 114 | } else { |
104 | (src_ptr.value.range(), node.text().to_string().replace("\n", " ")) | 115 | (node.value.text_range(), node.value.text().to_string().replace("\n", " ")) |
105 | }; | 116 | }; |
106 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; | 117 | let macro_prefix = if node.file_id != file_id.into() { "!" } else { "" }; |
107 | format_to!( | 118 | format_to!( |
108 | buf, | 119 | buf, |
109 | "{}{} '{}': {}\n", | 120 | "{}{} '{}': {}\n", |
@@ -114,11 +125,12 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String { | |||
114 | ); | 125 | ); |
115 | } | 126 | } |
116 | if include_mismatches { | 127 | if include_mismatches { |
117 | mismatches.sort_by_key(|(src_ptr, _)| { | 128 | mismatches.sort_by_key(|(node, _)| { |
118 | (src_ptr.value.range().start(), src_ptr.value.range().end()) | 129 | let range = node.value.text_range(); |
130 | (range.start(), range.end()) | ||
119 | }); | 131 | }); |
120 | for (src_ptr, mismatch) in &mismatches { | 132 | for (src_ptr, mismatch) in &mismatches { |
121 | let range = src_ptr.value.range(); | 133 | let range = src_ptr.value.text_range(); |
122 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; | 134 | let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; |
123 | format_to!( | 135 | format_to!( |
124 | buf, | 136 | buf, |
diff --git a/crates/ra_hir_ty/src/tests/patterns.rs b/crates/ra_hir_ty/src/tests/patterns.rs index 07cbc521a..6ea51d5d3 100644 --- a/crates/ra_hir_ty/src/tests/patterns.rs +++ b/crates/ra_hir_ty/src/tests/patterns.rs | |||
@@ -455,3 +455,29 @@ fn test() { | |||
455 | "### | 455 | "### |
456 | ); | 456 | ); |
457 | } | 457 | } |
458 | |||
459 | #[test] | ||
460 | fn infer_guard() { | ||
461 | assert_snapshot!( | ||
462 | infer(r#" | ||
463 | struct S; | ||
464 | impl S { fn foo(&self) -> bool { false } } | ||
465 | |||
466 | fn main() { | ||
467 | match S { | ||
468 | s if s.foo() => (), | ||
469 | } | ||
470 | } | ||
471 | "#), @" | ||
472 | [28; 32) 'self': &S | ||
473 | [42; 51) '{ false }': bool | ||
474 | [44; 49) 'false': bool | ||
475 | [65; 116) '{ ... } }': () | ||
476 | [71; 114) 'match ... }': () | ||
477 | [77; 78) 'S': S | ||
478 | [89; 90) 's': S | ||
479 | [94; 95) 's': S | ||
480 | [94; 101) 's.foo()': bool | ||
481 | [105; 107) '()': () | ||
482 | ") | ||
483 | } | ||
diff --git a/crates/ra_hir_ty/src/tests/regression.rs b/crates/ra_hir_ty/src/tests/regression.rs index 61284d672..61a6801fc 100644 --- a/crates/ra_hir_ty/src/tests/regression.rs +++ b/crates/ra_hir_ty/src/tests/regression.rs | |||
@@ -533,3 +533,44 @@ fn foo(b: Bar) { | |||
533 | "### | 533 | "### |
534 | ); | 534 | ); |
535 | } | 535 | } |
536 | |||
537 | #[test] | ||
538 | fn issue_4053_diesel_where_clauses() { | ||
539 | assert_snapshot!( | ||
540 | infer(r#" | ||
541 | trait BoxedDsl<DB> { | ||
542 | type Output; | ||
543 | fn internal_into_boxed(self) -> Self::Output; | ||
544 | } | ||
545 | |||
546 | struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> { | ||
547 | order: Order, | ||
548 | } | ||
549 | |||
550 | trait QueryFragment<DB: Backend> {} | ||
551 | |||
552 | trait Into<T> { fn into(self) -> T; } | ||
553 | |||
554 | impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB> | ||
555 | for SelectStatement<F, S, D, W, O, LOf, G> | ||
556 | where | ||
557 | O: Into<dyn QueryFragment<DB>>, | ||
558 | { | ||
559 | type Output = XXX; | ||
560 | |||
561 | fn internal_into_boxed(self) -> Self::Output { | ||
562 | self.order.into(); | ||
563 | } | ||
564 | } | ||
565 | "#), | ||
566 | @r###" | ||
567 | [66; 70) 'self': Self | ||
568 | [268; 272) 'self': Self | ||
569 | [467; 471) 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||
570 | [489; 523) '{ ... }': () | ||
571 | [499; 503) 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> | ||
572 | [499; 509) 'self.order': O | ||
573 | [499; 516) 'self.o...into()': dyn QueryFragment<DB> | ||
574 | "### | ||
575 | ); | ||
576 | } | ||
diff --git a/crates/ra_hir_ty/src/traits.rs b/crates/ra_hir_ty/src/traits.rs index 05791a848..6bc6d474c 100644 --- a/crates/ra_hir_ty/src/traits.rs +++ b/crates/ra_hir_ty/src/traits.rs | |||
@@ -225,7 +225,7 @@ fn solution_from_chalk( | |||
225 | None => unimplemented!(), | 225 | None => unimplemented!(), |
226 | }) | 226 | }) |
227 | .collect(); | 227 | .collect(); |
228 | let result = Canonical { value, num_vars: subst.binders.len() }; | 228 | let result = Canonical { value, num_vars: subst.binders.len(&Interner) }; |
229 | SolutionVariables(result) | 229 | SolutionVariables(result) |
230 | }; | 230 | }; |
231 | match solution { | 231 | match solution { |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index e00a82db2..1ccb7c3b4 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -4,8 +4,8 @@ use std::{fmt, sync::Arc}; | |||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{ | 6 | use chalk_ir::{ |
7 | cast::Cast, fold::shift::Shift, Goal, GoalData, Parameter, PlaceholderIndex, TypeName, | 7 | cast::Cast, fold::shift::Shift, interner::HasInterner, Goal, GoalData, Parameter, |
8 | UniverseIndex, | 8 | PlaceholderIndex, TypeName, UniverseIndex, |
9 | }; | 9 | }; |
10 | 10 | ||
11 | use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; | 11 | use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; |
@@ -33,8 +33,10 @@ impl chalk_ir::interner::Interner for Interner { | |||
33 | type InternedGoals = Vec<Goal<Self>>; | 33 | type InternedGoals = Vec<Goal<Self>>; |
34 | type InternedSubstitution = Vec<Parameter<Self>>; | 34 | type InternedSubstitution = Vec<Parameter<Self>>; |
35 | type InternedProgramClause = chalk_ir::ProgramClauseData<Self>; | 35 | type InternedProgramClause = chalk_ir::ProgramClauseData<Self>; |
36 | type InternedProgramClauses = Vec<chalk_ir::ProgramClause<Self>>; | 36 | type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; |
37 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; | 37 | type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; |
38 | type InternedParameterKinds = Vec<chalk_ir::ParameterKind<()>>; | ||
39 | type InternedCanonicalVarKinds = Vec<chalk_ir::ParameterKind<UniverseIndex>>; | ||
38 | type Identifier = TypeAliasId; | 40 | type Identifier = TypeAliasId; |
39 | type DefId = InternId; | 41 | type DefId = InternId; |
40 | 42 | ||
@@ -60,6 +62,27 @@ impl chalk_ir::interner::Interner for Interner { | |||
60 | tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) | 62 | tls::with_current_program(|prog| Some(prog?.debug_alias(alias, fmt))) |
61 | } | 63 | } |
62 | 64 | ||
65 | fn debug_projection_ty( | ||
66 | proj: &chalk_ir::ProjectionTy<Interner>, | ||
67 | fmt: &mut fmt::Formatter<'_>, | ||
68 | ) -> Option<fmt::Result> { | ||
69 | tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt))) | ||
70 | } | ||
71 | |||
72 | fn debug_opaque_ty( | ||
73 | opaque_ty: &chalk_ir::OpaqueTy<Interner>, | ||
74 | fmt: &mut fmt::Formatter<'_>, | ||
75 | ) -> Option<fmt::Result> { | ||
76 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty(opaque_ty, fmt))) | ||
77 | } | ||
78 | |||
79 | fn debug_opaque_ty_id( | ||
80 | opaque_ty_id: chalk_ir::OpaqueTyId<Self>, | ||
81 | fmt: &mut fmt::Formatter<'_>, | ||
82 | ) -> Option<fmt::Result> { | ||
83 | tls::with_current_program(|prog| Some(prog?.debug_opaque_ty_id(opaque_ty_id, fmt))) | ||
84 | } | ||
85 | |||
63 | fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { | 86 | fn debug_ty(ty: &chalk_ir::Ty<Interner>, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { |
64 | tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) | 87 | tls::with_current_program(|prog| Some(prog?.debug_ty(ty, fmt))) |
65 | } | 88 | } |
@@ -202,15 +225,15 @@ impl chalk_ir::interner::Interner for Interner { | |||
202 | fn intern_program_clauses( | 225 | fn intern_program_clauses( |
203 | &self, | 226 | &self, |
204 | data: impl IntoIterator<Item = chalk_ir::ProgramClause<Self>>, | 227 | data: impl IntoIterator<Item = chalk_ir::ProgramClause<Self>>, |
205 | ) -> Vec<chalk_ir::ProgramClause<Self>> { | 228 | ) -> Arc<[chalk_ir::ProgramClause<Self>]> { |
206 | data.into_iter().collect() | 229 | data.into_iter().collect() |
207 | } | 230 | } |
208 | 231 | ||
209 | fn program_clauses_data<'a>( | 232 | fn program_clauses_data<'a>( |
210 | &self, | 233 | &self, |
211 | clauses: &'a Vec<chalk_ir::ProgramClause<Self>>, | 234 | clauses: &'a Arc<[chalk_ir::ProgramClause<Self>]>, |
212 | ) -> &'a [chalk_ir::ProgramClause<Self>] { | 235 | ) -> &'a [chalk_ir::ProgramClause<Self>] { |
213 | clauses | 236 | &clauses |
214 | } | 237 | } |
215 | 238 | ||
216 | fn intern_quantified_where_clauses( | 239 | fn intern_quantified_where_clauses( |
@@ -226,6 +249,34 @@ impl chalk_ir::interner::Interner for Interner { | |||
226 | ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] { | 249 | ) -> &'a [chalk_ir::QuantifiedWhereClause<Self>] { |
227 | clauses | 250 | clauses |
228 | } | 251 | } |
252 | |||
253 | fn intern_parameter_kinds( | ||
254 | &self, | ||
255 | data: impl IntoIterator<Item = chalk_ir::ParameterKind<()>>, | ||
256 | ) -> Self::InternedParameterKinds { | ||
257 | data.into_iter().collect() | ||
258 | } | ||
259 | |||
260 | fn parameter_kinds_data<'a>( | ||
261 | &self, | ||
262 | parameter_kinds: &'a Self::InternedParameterKinds, | ||
263 | ) -> &'a [chalk_ir::ParameterKind<()>] { | ||
264 | ¶meter_kinds | ||
265 | } | ||
266 | |||
267 | fn intern_canonical_var_kinds( | ||
268 | &self, | ||
269 | data: impl IntoIterator<Item = chalk_ir::ParameterKind<UniverseIndex>>, | ||
270 | ) -> Self::InternedCanonicalVarKinds { | ||
271 | data.into_iter().collect() | ||
272 | } | ||
273 | |||
274 | fn canonical_var_kinds_data<'a>( | ||
275 | &self, | ||
276 | canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, | ||
277 | ) -> &'a [chalk_ir::ParameterKind<UniverseIndex>] { | ||
278 | &canonical_var_kinds | ||
279 | } | ||
229 | } | 280 | } |
230 | 281 | ||
231 | impl chalk_ir::interner::HasInterner for Interner { | 282 | impl chalk_ir::interner::HasInterner for Interner { |
@@ -268,9 +319,12 @@ impl ToChalk for Ty { | |||
268 | Ty::Projection(proj_ty) => { | 319 | Ty::Projection(proj_ty) => { |
269 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | 320 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); |
270 | let substitution = proj_ty.parameters.to_chalk(db); | 321 | let substitution = proj_ty.parameters.to_chalk(db); |
271 | chalk_ir::AliasTy { associated_ty_id, substitution } | 322 | chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy { |
272 | .cast(&Interner) | 323 | associated_ty_id, |
273 | .intern(&Interner) | 324 | substitution, |
325 | }) | ||
326 | .cast(&Interner) | ||
327 | .intern(&Interner) | ||
274 | } | 328 | } |
275 | Ty::Placeholder(id) => { | 329 | Ty::Placeholder(id) => { |
276 | let interned_id = db.intern_type_param_id(id); | 330 | let interned_id = db.intern_type_param_id(id); |
@@ -314,16 +368,17 @@ impl ToChalk for Ty { | |||
314 | ); | 368 | ); |
315 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) | 369 | Ty::Placeholder(db.lookup_intern_type_param_id(interned_id)) |
316 | } | 370 | } |
317 | chalk_ir::TyData::Alias(proj) => { | 371 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Projection(proj)) => { |
318 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 372 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
319 | let parameters = from_chalk(db, proj.substitution); | 373 | let parameters = from_chalk(db, proj.substitution); |
320 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 374 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
321 | } | 375 | } |
376 | chalk_ir::TyData::Alias(chalk_ir::AliasTy::Opaque(_)) => unimplemented!(), | ||
322 | chalk_ir::TyData::Function(_) => unimplemented!(), | 377 | chalk_ir::TyData::Function(_) => unimplemented!(), |
323 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), | 378 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx), |
324 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, | 379 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, |
325 | chalk_ir::TyData::Dyn(where_clauses) => { | 380 | chalk_ir::TyData::Dyn(where_clauses) => { |
326 | assert_eq!(where_clauses.bounds.binders.len(), 1); | 381 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); |
327 | let predicates = where_clauses | 382 | let predicates = where_clauses |
328 | .bounds | 383 | .bounds |
329 | .skip_binders() | 384 | .skip_binders() |
@@ -404,6 +459,7 @@ impl ToChalk for TypeCtor { | |||
404 | match type_name { | 459 | match type_name { |
405 | TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), | 460 | TypeName::Struct(struct_id) => db.lookup_intern_type_ctor(struct_id.into()), |
406 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), | 461 | TypeName::AssociatedType(type_id) => TypeCtor::AssociatedType(from_chalk(db, type_id)), |
462 | TypeName::OpaqueType(_) => unreachable!(), | ||
407 | TypeName::Error => { | 463 | TypeName::Error => { |
408 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor | 464 | // this should not be reached, since we don't represent TypeName::Error with TypeCtor |
409 | unreachable!() | 465 | unreachable!() |
@@ -460,7 +516,8 @@ impl ToChalk for GenericPredicate { | |||
460 | } | 516 | } |
461 | GenericPredicate::Projection(projection_pred) => { | 517 | GenericPredicate::Projection(projection_pred) => { |
462 | let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); | 518 | let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); |
463 | let alias = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); | 519 | let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); |
520 | let alias = chalk_ir::AliasTy::Projection(projection); | ||
464 | make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) | 521 | make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) |
465 | } | 522 | } |
466 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), | 523 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), |
@@ -481,7 +538,13 @@ impl ToChalk for GenericPredicate { | |||
481 | GenericPredicate::Implemented(from_chalk(db, tr)) | 538 | GenericPredicate::Implemented(from_chalk(db, tr)) |
482 | } | 539 | } |
483 | chalk_ir::WhereClause::AliasEq(projection_eq) => { | 540 | chalk_ir::WhereClause::AliasEq(projection_eq) => { |
484 | let projection_ty = from_chalk(db, projection_eq.alias); | 541 | let projection_ty = from_chalk( |
542 | db, | ||
543 | match projection_eq.alias { | ||
544 | chalk_ir::AliasTy::Projection(p) => p, | ||
545 | _ => unimplemented!(), | ||
546 | }, | ||
547 | ); | ||
485 | let ty = from_chalk(db, projection_eq.ty); | 548 | let ty = from_chalk(db, projection_eq.ty); |
486 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) | 549 | GenericPredicate::Projection(super::ProjectionPredicate { projection_ty, ty }) |
487 | } | 550 | } |
@@ -490,10 +553,10 @@ impl ToChalk for GenericPredicate { | |||
490 | } | 553 | } |
491 | 554 | ||
492 | impl ToChalk for ProjectionTy { | 555 | impl ToChalk for ProjectionTy { |
493 | type Chalk = chalk_ir::AliasTy<Interner>; | 556 | type Chalk = chalk_ir::ProjectionTy<Interner>; |
494 | 557 | ||
495 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasTy<Interner> { | 558 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> { |
496 | chalk_ir::AliasTy { | 559 | chalk_ir::ProjectionTy { |
497 | associated_ty_id: self.associated_ty.to_chalk(db), | 560 | associated_ty_id: self.associated_ty.to_chalk(db), |
498 | substitution: self.parameters.to_chalk(db), | 561 | substitution: self.parameters.to_chalk(db), |
499 | } | 562 | } |
@@ -501,7 +564,7 @@ impl ToChalk for ProjectionTy { | |||
501 | 564 | ||
502 | fn from_chalk( | 565 | fn from_chalk( |
503 | db: &dyn HirDatabase, | 566 | db: &dyn HirDatabase, |
504 | projection_ty: chalk_ir::AliasTy<Interner>, | 567 | projection_ty: chalk_ir::ProjectionTy<Interner>, |
505 | ) -> ProjectionTy { | 568 | ) -> ProjectionTy { |
506 | ProjectionTy { | 569 | ProjectionTy { |
507 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | 570 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), |
@@ -514,7 +577,10 @@ impl ToChalk for super::ProjectionPredicate { | |||
514 | type Chalk = chalk_ir::AliasEq<Interner>; | 577 | type Chalk = chalk_ir::AliasEq<Interner>; |
515 | 578 | ||
516 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { | 579 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { |
517 | chalk_ir::AliasEq { alias: self.projection_ty.to_chalk(db), ty: self.ty.to_chalk(db) } | 580 | chalk_ir::AliasEq { |
581 | alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)), | ||
582 | ty: self.ty.to_chalk(db), | ||
583 | } | ||
518 | } | 584 | } |
519 | 585 | ||
520 | fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { | 586 | fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { |
@@ -540,17 +606,24 @@ impl ToChalk for Obligation { | |||
540 | impl<T> ToChalk for Canonical<T> | 606 | impl<T> ToChalk for Canonical<T> |
541 | where | 607 | where |
542 | T: ToChalk, | 608 | T: ToChalk, |
609 | T::Chalk: HasInterner<Interner = Interner>, | ||
543 | { | 610 | { |
544 | type Chalk = chalk_ir::Canonical<T::Chalk>; | 611 | type Chalk = chalk_ir::Canonical<T::Chalk>; |
545 | 612 | ||
546 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | 613 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { |
547 | let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT); | 614 | let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT); |
548 | let value = self.value.to_chalk(db); | 615 | let value = self.value.to_chalk(db); |
549 | chalk_ir::Canonical { value, binders: vec![parameter; self.num_vars] } | 616 | chalk_ir::Canonical { |
617 | value, | ||
618 | binders: chalk_ir::CanonicalVarKinds::from(&Interner, vec![parameter; self.num_vars]), | ||
619 | } | ||
550 | } | 620 | } |
551 | 621 | ||
552 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | 622 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { |
553 | Canonical { num_vars: canonical.binders.len(), value: from_chalk(db, canonical.value) } | 623 | Canonical { |
624 | num_vars: canonical.binders.len(&Interner), | ||
625 | value: from_chalk(db, canonical.value), | ||
626 | } | ||
554 | } | 627 | } |
555 | } | 628 | } |
556 | 629 | ||
@@ -649,9 +722,15 @@ impl ToChalk for builtin::BuiltinImplAssocTyValueData { | |||
649 | } | 722 | } |
650 | } | 723 | } |
651 | 724 | ||
652 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | 725 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> |
726 | where | ||
727 | T: HasInterner<Interner = Interner>, | ||
728 | { | ||
653 | chalk_ir::Binders::new( | 729 | chalk_ir::Binders::new( |
654 | std::iter::repeat(chalk_ir::ParameterKind::Ty(())).take(num_vars).collect(), | 730 | chalk_ir::ParameterKinds::from( |
731 | &Interner, | ||
732 | std::iter::repeat(chalk_ir::ParameterKind::Ty(())).take(num_vars), | ||
733 | ), | ||
655 | value, | 734 | value, |
656 | ) | 735 | ) |
657 | } | 736 | } |
@@ -799,6 +878,28 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
799 | // FIXME tell Chalk about well-known traits (here and in trait_datum) | 878 | // FIXME tell Chalk about well-known traits (here and in trait_datum) |
800 | None | 879 | None |
801 | } | 880 | } |
881 | |||
882 | fn program_clauses_for_env( | ||
883 | &self, | ||
884 | environment: &chalk_ir::Environment<Interner>, | ||
885 | ) -> chalk_ir::ProgramClauses<Interner> { | ||
886 | self.db.program_clauses_for_chalk_env(self.krate, environment.clone()) | ||
887 | } | ||
888 | |||
889 | fn opaque_ty_data( | ||
890 | &self, | ||
891 | _id: chalk_ir::OpaqueTyId<Interner>, | ||
892 | ) -> Arc<chalk_rust_ir::OpaqueTyDatum<Interner>> { | ||
893 | unimplemented!() | ||
894 | } | ||
895 | } | ||
896 | |||
897 | pub(crate) fn program_clauses_for_chalk_env_query( | ||
898 | db: &dyn HirDatabase, | ||
899 | krate: CrateId, | ||
900 | environment: chalk_ir::Environment<Interner>, | ||
901 | ) -> chalk_ir::ProgramClauses<Interner> { | ||
902 | chalk_solve::program_clauses_for_env(&ChalkContext { db, krate }, &environment) | ||
802 | } | 903 | } |
803 | 904 | ||
804 | pub(crate) fn associated_ty_data_query( | 905 | pub(crate) fn associated_ty_data_query( |
diff --git a/crates/ra_hir_ty/src/traits/chalk/tls.rs b/crates/ra_hir_ty/src/traits/chalk/tls.rs index fa8e4d1ad..4867cb17e 100644 --- a/crates/ra_hir_ty/src/traits/chalk/tls.rs +++ b/crates/ra_hir_ty/src/traits/chalk/tls.rs | |||
@@ -121,19 +121,38 @@ impl DebugContext<'_> { | |||
121 | write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) | 121 | write!(fmt, "{}::{}", trait_data.name, type_alias_data.name) |
122 | } | 122 | } |
123 | 123 | ||
124 | pub fn debug_opaque_ty_id( | ||
125 | &self, | ||
126 | opaque_ty_id: chalk_ir::OpaqueTyId<Interner>, | ||
127 | fmt: &mut fmt::Formatter<'_>, | ||
128 | ) -> Result<(), fmt::Error> { | ||
129 | fmt.debug_struct("OpaqueTyId").field("index", &opaque_ty_id.0).finish() | ||
130 | } | ||
131 | |||
124 | pub fn debug_alias( | 132 | pub fn debug_alias( |
125 | &self, | 133 | &self, |
126 | alias: &AliasTy<Interner>, | 134 | alias_ty: &AliasTy<Interner>, |
135 | fmt: &mut fmt::Formatter<'_>, | ||
136 | ) -> Result<(), fmt::Error> { | ||
137 | match alias_ty { | ||
138 | AliasTy::Projection(projection_ty) => self.debug_projection_ty(projection_ty, fmt), | ||
139 | AliasTy::Opaque(opaque_ty) => self.debug_opaque_ty(opaque_ty, fmt), | ||
140 | } | ||
141 | } | ||
142 | |||
143 | pub fn debug_projection_ty( | ||
144 | &self, | ||
145 | projection_ty: &chalk_ir::ProjectionTy<Interner>, | ||
127 | fmt: &mut fmt::Formatter<'_>, | 146 | fmt: &mut fmt::Formatter<'_>, |
128 | ) -> Result<(), fmt::Error> { | 147 | ) -> Result<(), fmt::Error> { |
129 | let type_alias: TypeAliasId = from_chalk(self.0, alias.associated_ty_id); | 148 | let type_alias: TypeAliasId = from_chalk(self.0, projection_ty.associated_ty_id); |
130 | let type_alias_data = self.0.type_alias_data(type_alias); | 149 | let type_alias_data = self.0.type_alias_data(type_alias); |
131 | let trait_ = match type_alias.lookup(self.0.upcast()).container { | 150 | let trait_ = match type_alias.lookup(self.0.upcast()).container { |
132 | AssocContainerId::TraitId(t) => t, | 151 | AssocContainerId::TraitId(t) => t, |
133 | _ => panic!("associated type not in trait"), | 152 | _ => panic!("associated type not in trait"), |
134 | }; | 153 | }; |
135 | let trait_data = self.0.trait_data(trait_); | 154 | let trait_data = self.0.trait_data(trait_); |
136 | let params = alias.substitution.parameters(&Interner); | 155 | let params = projection_ty.substitution.parameters(&Interner); |
137 | write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; | 156 | write!(fmt, "<{:?} as {}", ¶ms[0], trait_data.name,)?; |
138 | if params.len() > 1 { | 157 | if params.len() > 1 { |
139 | write!( | 158 | write!( |
@@ -145,6 +164,14 @@ impl DebugContext<'_> { | |||
145 | write!(fmt, ">::{}", type_alias_data.name) | 164 | write!(fmt, ">::{}", type_alias_data.name) |
146 | } | 165 | } |
147 | 166 | ||
167 | pub fn debug_opaque_ty( | ||
168 | &self, | ||
169 | opaque_ty: &chalk_ir::OpaqueTy<Interner>, | ||
170 | fmt: &mut fmt::Formatter<'_>, | ||
171 | ) -> Result<(), fmt::Error> { | ||
172 | write!(fmt, "{:?}", opaque_ty.opaque_ty_id) | ||
173 | } | ||
174 | |||
148 | pub fn debug_ty( | 175 | pub fn debug_ty( |
149 | &self, | 176 | &self, |
150 | ty: &chalk_ir::Ty<Interner>, | 177 | ty: &chalk_ir::Ty<Interner>, |
diff --git a/crates/ra_ide/src/assists.rs b/crates/ra_ide/src/assists.rs index 40d56a4f7..2b5d11681 100644 --- a/crates/ra_ide/src/assists.rs +++ b/crates/ra_ide/src/assists.rs | |||
@@ -37,6 +37,10 @@ fn action_to_edit( | |||
37 | file_id: FileId, | 37 | file_id: FileId, |
38 | assist_label: &AssistLabel, | 38 | assist_label: &AssistLabel, |
39 | ) -> SourceChange { | 39 | ) -> SourceChange { |
40 | let file_id = match action.file { | ||
41 | ra_assists::AssistFile::TargetFile(it) => it, | ||
42 | _ => file_id, | ||
43 | }; | ||
40 | let file_edit = SourceFileEdit { file_id, edit: action.edit }; | 44 | let file_edit = SourceFileEdit { file_id, edit: action.edit }; |
41 | SourceChange::source_file_edit(assist_label.label.clone(), file_edit) | 45 | SourceChange::source_file_edit(assist_label.label.clone(), file_edit) |
42 | .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id })) | 46 | .with_cursor_opt(action.cursor_position.map(|offset| FilePosition { offset, file_id })) |
diff --git a/crates/ra_ide/src/call_info.rs b/crates/ra_ide/src/call_info.rs index f95b6baf3..5da254a6e 100644 --- a/crates/ra_ide/src/call_info.rs +++ b/crates/ra_ide/src/call_info.rs | |||
@@ -19,10 +19,24 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
19 | call_info_for_token(&sema, token) | 19 | call_info_for_token(&sema, token) |
20 | } | 20 | } |
21 | 21 | ||
22 | pub(crate) fn call_info_for_token( | 22 | #[derive(Debug)] |
23 | sema: &Semantics<RootDatabase>, | 23 | pub(crate) struct ActiveParameter { |
24 | token: SyntaxToken, | 24 | /// FIXME: should be `Type` and `Name |
25 | ) -> Option<CallInfo> { | 25 | pub(crate) ty: String, |
26 | pub(crate) name: String, | ||
27 | } | ||
28 | |||
29 | impl ActiveParameter { | ||
30 | pub(crate) fn at(db: &RootDatabase, position: FilePosition) -> Option<Self> { | ||
31 | call_info(db, position)?.into_active_parameter() | ||
32 | } | ||
33 | |||
34 | pub(crate) fn at_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<Self> { | ||
35 | call_info_for_token(sema, token)?.into_active_parameter() | ||
36 | } | ||
37 | } | ||
38 | |||
39 | fn call_info_for_token(sema: &Semantics<RootDatabase>, token: SyntaxToken) -> Option<CallInfo> { | ||
26 | // Find the calling expression and it's NameRef | 40 | // Find the calling expression and it's NameRef |
27 | let calling_node = FnCallNode::with_node(&token.parent())?; | 41 | let calling_node = FnCallNode::with_node(&token.parent())?; |
28 | 42 | ||
@@ -160,6 +174,14 @@ impl FnCallNode { | |||
160 | } | 174 | } |
161 | 175 | ||
162 | impl CallInfo { | 176 | impl CallInfo { |
177 | fn into_active_parameter(self) -> Option<ActiveParameter> { | ||
178 | let idx = self.active_parameter?; | ||
179 | let ty = self.signature.parameter_types.get(idx)?.clone(); | ||
180 | let name = self.signature.parameter_names.get(idx)?.clone(); | ||
181 | let res = ActiveParameter { ty, name }; | ||
182 | Some(res) | ||
183 | } | ||
184 | |||
163 | fn with_fn(db: &RootDatabase, function: hir::Function) -> Self { | 185 | fn with_fn(db: &RootDatabase, function: hir::Function) -> Self { |
164 | let signature = FunctionSignature::from_hir(db, function); | 186 | let signature = FunctionSignature::from_hir(db, function); |
165 | 187 | ||
diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index 4a1a2a04a..4ca0fdf4f 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs | |||
@@ -1,9 +1,11 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | mod completion_config; | ||
3 | mod completion_item; | 4 | mod completion_item; |
4 | mod completion_context; | 5 | mod completion_context; |
5 | mod presentation; | 6 | mod presentation; |
6 | 7 | ||
8 | mod complete_attribute; | ||
7 | mod complete_dot; | 9 | mod complete_dot; |
8 | mod complete_record; | 10 | mod complete_record; |
9 | mod complete_pattern; | 11 | mod complete_pattern; |
@@ -28,27 +30,11 @@ use crate::{ | |||
28 | FilePosition, | 30 | FilePosition, |
29 | }; | 31 | }; |
30 | 32 | ||
31 | pub use crate::completion::completion_item::{ | 33 | pub use crate::completion::{ |
32 | CompletionItem, CompletionItemKind, InsertTextFormat, | 34 | completion_config::CompletionConfig, |
35 | completion_item::{CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat}, | ||
33 | }; | 36 | }; |
34 | 37 | ||
35 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
36 | pub struct CompletionConfig { | ||
37 | pub enable_postfix_completions: bool, | ||
38 | pub add_call_parenthesis: bool, | ||
39 | pub add_call_argument_snippets: bool, | ||
40 | } | ||
41 | |||
42 | impl Default for CompletionConfig { | ||
43 | fn default() -> Self { | ||
44 | CompletionConfig { | ||
45 | enable_postfix_completions: true, | ||
46 | add_call_parenthesis: true, | ||
47 | add_call_argument_snippets: true, | ||
48 | } | ||
49 | } | ||
50 | } | ||
51 | |||
52 | /// Main entry point for completion. We run completion as a two-phase process. | 38 | /// Main entry point for completion. We run completion as a two-phase process. |
53 | /// | 39 | /// |
54 | /// First, we look at the position and collect a so-called `CompletionContext. | 40 | /// First, we look at the position and collect a so-called `CompletionContext. |
@@ -93,6 +79,7 @@ pub(crate) fn completions( | |||
93 | complete_postfix::complete_postfix(&mut acc, &ctx); | 79 | complete_postfix::complete_postfix(&mut acc, &ctx); |
94 | complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); | 80 | complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); |
95 | complete_trait_impl::complete_trait_impl(&mut acc, &ctx); | 81 | complete_trait_impl::complete_trait_impl(&mut acc, &ctx); |
82 | complete_attribute::complete_attribute(&mut acc, &ctx); | ||
96 | 83 | ||
97 | Some(acc) | 84 | Some(acc) |
98 | } | 85 | } |
diff --git a/crates/ra_ide/src/completion/complete_attribute.rs b/crates/ra_ide/src/completion/complete_attribute.rs new file mode 100644 index 000000000..b405042e8 --- /dev/null +++ b/crates/ra_ide/src/completion/complete_attribute.rs | |||
@@ -0,0 +1,587 @@ | |||
1 | //! Completion for attributes | ||
2 | //! | ||
3 | //! This module uses a bit of static metadata to provide completions | ||
4 | //! for built-in attributes. | ||
5 | |||
6 | use super::completion_context::CompletionContext; | ||
7 | use super::completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions}; | ||
8 | use ra_syntax::{ | ||
9 | ast::{Attr, AttrKind}, | ||
10 | AstNode, | ||
11 | }; | ||
12 | |||
13 | pub(super) fn complete_attribute(acc: &mut Completions, ctx: &CompletionContext) { | ||
14 | if !ctx.is_attribute { | ||
15 | return; | ||
16 | } | ||
17 | |||
18 | let is_inner = ctx | ||
19 | .original_token | ||
20 | .ancestors() | ||
21 | .find_map(Attr::cast) | ||
22 | .map(|attr| attr.kind() == AttrKind::Inner) | ||
23 | .unwrap_or(false); | ||
24 | |||
25 | for attr_completion in ATTRIBUTES { | ||
26 | let mut item = CompletionItem::new( | ||
27 | CompletionKind::Attribute, | ||
28 | ctx.source_range(), | ||
29 | attr_completion.label, | ||
30 | ) | ||
31 | .kind(CompletionItemKind::Attribute); | ||
32 | |||
33 | match (attr_completion.snippet, ctx.config.snippet_cap) { | ||
34 | (Some(snippet), Some(cap)) => { | ||
35 | item = item.insert_snippet(cap, snippet); | ||
36 | } | ||
37 | _ => {} | ||
38 | } | ||
39 | |||
40 | if is_inner || !attr_completion.should_be_inner { | ||
41 | acc.add(item); | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | |||
46 | struct AttrCompletion { | ||
47 | label: &'static str, | ||
48 | snippet: Option<&'static str>, | ||
49 | should_be_inner: bool, | ||
50 | } | ||
51 | |||
52 | const ATTRIBUTES: &[AttrCompletion] = &[ | ||
53 | AttrCompletion { label: "allow", snippet: Some("allow(${0:lint})"), should_be_inner: false }, | ||
54 | AttrCompletion { | ||
55 | label: "cfg_attr", | ||
56 | snippet: Some("cfg_attr(${1:predicate}, ${0:attr})"), | ||
57 | should_be_inner: false, | ||
58 | }, | ||
59 | AttrCompletion { label: "cfg", snippet: Some("cfg(${0:predicate})"), should_be_inner: false }, | ||
60 | AttrCompletion { label: "deny", snippet: Some("deny(${0:lint})"), should_be_inner: false }, | ||
61 | AttrCompletion { | ||
62 | label: "deprecated", | ||
63 | snippet: Some(r#"deprecated = "${0:reason}""#), | ||
64 | should_be_inner: false, | ||
65 | }, | ||
66 | AttrCompletion { | ||
67 | label: "derive", | ||
68 | snippet: Some(r#"derive(${0:Debug})"#), | ||
69 | should_be_inner: false, | ||
70 | }, | ||
71 | AttrCompletion { label: "doc", snippet: Some(r#"doc = "${0:docs}""#), should_be_inner: false }, | ||
72 | AttrCompletion { label: "feature", snippet: Some("feature(${0:flag})"), should_be_inner: true }, | ||
73 | AttrCompletion { label: "forbid", snippet: Some("forbid(${0:lint})"), should_be_inner: false }, | ||
74 | // FIXME: resolve through macro resolution? | ||
75 | AttrCompletion { label: "global_allocator", snippet: None, should_be_inner: true }, | ||
76 | AttrCompletion { label: "ignore", snippet: Some("ignore(${0:lint})"), should_be_inner: false }, | ||
77 | AttrCompletion { label: "inline", snippet: Some("inline(${0:lint})"), should_be_inner: false }, | ||
78 | AttrCompletion { | ||
79 | label: "link_name", | ||
80 | snippet: Some(r#"link_name = "${0:symbol_name}""#), | ||
81 | should_be_inner: false, | ||
82 | }, | ||
83 | AttrCompletion { label: "link", snippet: None, should_be_inner: false }, | ||
84 | AttrCompletion { label: "macro_export", snippet: None, should_be_inner: false }, | ||
85 | AttrCompletion { label: "macro_use", snippet: None, should_be_inner: false }, | ||
86 | AttrCompletion { | ||
87 | label: "must_use", | ||
88 | snippet: Some(r#"must_use = "${0:reason}""#), | ||
89 | should_be_inner: false, | ||
90 | }, | ||
91 | AttrCompletion { label: "no_mangle", snippet: None, should_be_inner: false }, | ||
92 | AttrCompletion { label: "no_std", snippet: None, should_be_inner: true }, | ||
93 | AttrCompletion { label: "non_exhaustive", snippet: None, should_be_inner: false }, | ||
94 | AttrCompletion { label: "panic_handler", snippet: None, should_be_inner: true }, | ||
95 | AttrCompletion { label: "path", snippet: Some("path =\"${0:path}\""), should_be_inner: false }, | ||
96 | AttrCompletion { label: "proc_macro", snippet: None, should_be_inner: false }, | ||
97 | AttrCompletion { label: "proc_macro_attribute", snippet: None, should_be_inner: false }, | ||
98 | AttrCompletion { | ||
99 | label: "proc_macro_derive", | ||
100 | snippet: Some("proc_macro_derive(${0:Trait})"), | ||
101 | should_be_inner: false, | ||
102 | }, | ||
103 | AttrCompletion { | ||
104 | label: "recursion_limit", | ||
105 | snippet: Some("recursion_limit = ${0:128}"), | ||
106 | should_be_inner: true, | ||
107 | }, | ||
108 | AttrCompletion { label: "repr", snippet: Some("repr(${0:C})"), should_be_inner: false }, | ||
109 | AttrCompletion { | ||
110 | label: "should_panic", | ||
111 | snippet: Some(r#"expected = "${0:reason}""#), | ||
112 | should_be_inner: false, | ||
113 | }, | ||
114 | AttrCompletion { | ||
115 | label: "target_feature", | ||
116 | snippet: Some("target_feature = \"${0:feature}\""), | ||
117 | should_be_inner: false, | ||
118 | }, | ||
119 | AttrCompletion { label: "test", snippet: None, should_be_inner: false }, | ||
120 | AttrCompletion { label: "used", snippet: None, should_be_inner: false }, | ||
121 | AttrCompletion { label: "warn", snippet: Some("warn(${0:lint})"), should_be_inner: false }, | ||
122 | AttrCompletion { | ||
123 | label: "windows_subsystem", | ||
124 | snippet: Some(r#"windows_subsystem = "${0:subsystem}""#), | ||
125 | should_be_inner: true, | ||
126 | }, | ||
127 | ]; | ||
128 | |||
129 | #[cfg(test)] | ||
130 | mod tests { | ||
131 | use crate::completion::{test_utils::do_completion, CompletionItem, CompletionKind}; | ||
132 | use insta::assert_debug_snapshot; | ||
133 | |||
134 | fn do_attr_completion(code: &str) -> Vec<CompletionItem> { | ||
135 | do_completion(code, CompletionKind::Attribute) | ||
136 | } | ||
137 | |||
138 | #[test] | ||
139 | fn test_attribute_completion() { | ||
140 | assert_debug_snapshot!( | ||
141 | do_attr_completion( | ||
142 | r" | ||
143 | #[<|>] | ||
144 | ", | ||
145 | ), | ||
146 | @r###" | ||
147 | [ | ||
148 | CompletionItem { | ||
149 | label: "allow", | ||
150 | source_range: [19; 19), | ||
151 | delete: [19; 19), | ||
152 | insert: "allow(${0:lint})", | ||
153 | kind: Attribute, | ||
154 | }, | ||
155 | CompletionItem { | ||
156 | label: "cfg", | ||
157 | source_range: [19; 19), | ||
158 | delete: [19; 19), | ||
159 | insert: "cfg(${0:predicate})", | ||
160 | kind: Attribute, | ||
161 | }, | ||
162 | CompletionItem { | ||
163 | label: "cfg_attr", | ||
164 | source_range: [19; 19), | ||
165 | delete: [19; 19), | ||
166 | insert: "cfg_attr(${1:predicate}, ${0:attr})", | ||
167 | kind: Attribute, | ||
168 | }, | ||
169 | CompletionItem { | ||
170 | label: "deny", | ||
171 | source_range: [19; 19), | ||
172 | delete: [19; 19), | ||
173 | insert: "deny(${0:lint})", | ||
174 | kind: Attribute, | ||
175 | }, | ||
176 | CompletionItem { | ||
177 | label: "deprecated", | ||
178 | source_range: [19; 19), | ||
179 | delete: [19; 19), | ||
180 | insert: "deprecated = \"${0:reason}\"", | ||
181 | kind: Attribute, | ||
182 | }, | ||
183 | CompletionItem { | ||
184 | label: "derive", | ||
185 | source_range: [19; 19), | ||
186 | delete: [19; 19), | ||
187 | insert: "derive(${0:Debug})", | ||
188 | kind: Attribute, | ||
189 | }, | ||
190 | CompletionItem { | ||
191 | label: "doc", | ||
192 | source_range: [19; 19), | ||
193 | delete: [19; 19), | ||
194 | insert: "doc = \"${0:docs}\"", | ||
195 | kind: Attribute, | ||
196 | }, | ||
197 | CompletionItem { | ||
198 | label: "forbid", | ||
199 | source_range: [19; 19), | ||
200 | delete: [19; 19), | ||
201 | insert: "forbid(${0:lint})", | ||
202 | kind: Attribute, | ||
203 | }, | ||
204 | CompletionItem { | ||
205 | label: "ignore", | ||
206 | source_range: [19; 19), | ||
207 | delete: [19; 19), | ||
208 | insert: "ignore(${0:lint})", | ||
209 | kind: Attribute, | ||
210 | }, | ||
211 | CompletionItem { | ||
212 | label: "inline", | ||
213 | source_range: [19; 19), | ||
214 | delete: [19; 19), | ||
215 | insert: "inline(${0:lint})", | ||
216 | kind: Attribute, | ||
217 | }, | ||
218 | CompletionItem { | ||
219 | label: "link", | ||
220 | source_range: [19; 19), | ||
221 | delete: [19; 19), | ||
222 | insert: "link", | ||
223 | kind: Attribute, | ||
224 | }, | ||
225 | CompletionItem { | ||
226 | label: "link_name", | ||
227 | source_range: [19; 19), | ||
228 | delete: [19; 19), | ||
229 | insert: "link_name = \"${0:symbol_name}\"", | ||
230 | kind: Attribute, | ||
231 | }, | ||
232 | CompletionItem { | ||
233 | label: "macro_export", | ||
234 | source_range: [19; 19), | ||
235 | delete: [19; 19), | ||
236 | insert: "macro_export", | ||
237 | kind: Attribute, | ||
238 | }, | ||
239 | CompletionItem { | ||
240 | label: "macro_use", | ||
241 | source_range: [19; 19), | ||
242 | delete: [19; 19), | ||
243 | insert: "macro_use", | ||
244 | kind: Attribute, | ||
245 | }, | ||
246 | CompletionItem { | ||
247 | label: "must_use", | ||
248 | source_range: [19; 19), | ||
249 | delete: [19; 19), | ||
250 | insert: "must_use = \"${0:reason}\"", | ||
251 | kind: Attribute, | ||
252 | }, | ||
253 | CompletionItem { | ||
254 | label: "no_mangle", | ||
255 | source_range: [19; 19), | ||
256 | delete: [19; 19), | ||
257 | insert: "no_mangle", | ||
258 | kind: Attribute, | ||
259 | }, | ||
260 | CompletionItem { | ||
261 | label: "non_exhaustive", | ||
262 | source_range: [19; 19), | ||
263 | delete: [19; 19), | ||
264 | insert: "non_exhaustive", | ||
265 | kind: Attribute, | ||
266 | }, | ||
267 | CompletionItem { | ||
268 | label: "path", | ||
269 | source_range: [19; 19), | ||
270 | delete: [19; 19), | ||
271 | insert: "path =\"${0:path}\"", | ||
272 | kind: Attribute, | ||
273 | }, | ||
274 | CompletionItem { | ||
275 | label: "proc_macro", | ||
276 | source_range: [19; 19), | ||
277 | delete: [19; 19), | ||
278 | insert: "proc_macro", | ||
279 | kind: Attribute, | ||
280 | }, | ||
281 | CompletionItem { | ||
282 | label: "proc_macro_attribute", | ||
283 | source_range: [19; 19), | ||
284 | delete: [19; 19), | ||
285 | insert: "proc_macro_attribute", | ||
286 | kind: Attribute, | ||
287 | }, | ||
288 | CompletionItem { | ||
289 | label: "proc_macro_derive", | ||
290 | source_range: [19; 19), | ||
291 | delete: [19; 19), | ||
292 | insert: "proc_macro_derive(${0:Trait})", | ||
293 | kind: Attribute, | ||
294 | }, | ||
295 | CompletionItem { | ||
296 | label: "repr", | ||
297 | source_range: [19; 19), | ||
298 | delete: [19; 19), | ||
299 | insert: "repr(${0:C})", | ||
300 | kind: Attribute, | ||
301 | }, | ||
302 | CompletionItem { | ||
303 | label: "should_panic", | ||
304 | source_range: [19; 19), | ||
305 | delete: [19; 19), | ||
306 | insert: "expected = \"${0:reason}\"", | ||
307 | kind: Attribute, | ||
308 | }, | ||
309 | CompletionItem { | ||
310 | label: "target_feature", | ||
311 | source_range: [19; 19), | ||
312 | delete: [19; 19), | ||
313 | insert: "target_feature = \"${0:feature}\"", | ||
314 | kind: Attribute, | ||
315 | }, | ||
316 | CompletionItem { | ||
317 | label: "test", | ||
318 | source_range: [19; 19), | ||
319 | delete: [19; 19), | ||
320 | insert: "test", | ||
321 | kind: Attribute, | ||
322 | }, | ||
323 | CompletionItem { | ||
324 | label: "used", | ||
325 | source_range: [19; 19), | ||
326 | delete: [19; 19), | ||
327 | insert: "used", | ||
328 | kind: Attribute, | ||
329 | }, | ||
330 | CompletionItem { | ||
331 | label: "warn", | ||
332 | source_range: [19; 19), | ||
333 | delete: [19; 19), | ||
334 | insert: "warn(${0:lint})", | ||
335 | kind: Attribute, | ||
336 | }, | ||
337 | ] | ||
338 | "### | ||
339 | ); | ||
340 | } | ||
341 | |||
342 | #[test] | ||
343 | fn test_inner_attribute_completion() { | ||
344 | assert_debug_snapshot!( | ||
345 | do_attr_completion( | ||
346 | r" | ||
347 | #![<|>] | ||
348 | ", | ||
349 | ), | ||
350 | @r###" | ||
351 | [ | ||
352 | CompletionItem { | ||
353 | label: "allow", | ||
354 | source_range: [20; 20), | ||
355 | delete: [20; 20), | ||
356 | insert: "allow(${0:lint})", | ||
357 | kind: Attribute, | ||
358 | }, | ||
359 | CompletionItem { | ||
360 | label: "cfg", | ||
361 | source_range: [20; 20), | ||
362 | delete: [20; 20), | ||
363 | insert: "cfg(${0:predicate})", | ||
364 | kind: Attribute, | ||
365 | }, | ||
366 | CompletionItem { | ||
367 | label: "cfg_attr", | ||
368 | source_range: [20; 20), | ||
369 | delete: [20; 20), | ||
370 | insert: "cfg_attr(${1:predicate}, ${0:attr})", | ||
371 | kind: Attribute, | ||
372 | }, | ||
373 | CompletionItem { | ||
374 | label: "deny", | ||
375 | source_range: [20; 20), | ||
376 | delete: [20; 20), | ||
377 | insert: "deny(${0:lint})", | ||
378 | kind: Attribute, | ||
379 | }, | ||
380 | CompletionItem { | ||
381 | label: "deprecated", | ||
382 | source_range: [20; 20), | ||
383 | delete: [20; 20), | ||
384 | insert: "deprecated = \"${0:reason}\"", | ||
385 | kind: Attribute, | ||
386 | }, | ||
387 | CompletionItem { | ||
388 | label: "derive", | ||
389 | source_range: [20; 20), | ||
390 | delete: [20; 20), | ||
391 | insert: "derive(${0:Debug})", | ||
392 | kind: Attribute, | ||
393 | }, | ||
394 | CompletionItem { | ||
395 | label: "doc", | ||
396 | source_range: [20; 20), | ||
397 | delete: [20; 20), | ||
398 | insert: "doc = \"${0:docs}\"", | ||
399 | kind: Attribute, | ||
400 | }, | ||
401 | CompletionItem { | ||
402 | label: "feature", | ||
403 | source_range: [20; 20), | ||
404 | delete: [20; 20), | ||
405 | insert: "feature(${0:flag})", | ||
406 | kind: Attribute, | ||
407 | }, | ||
408 | CompletionItem { | ||
409 | label: "forbid", | ||
410 | source_range: [20; 20), | ||
411 | delete: [20; 20), | ||
412 | insert: "forbid(${0:lint})", | ||
413 | kind: Attribute, | ||
414 | }, | ||
415 | CompletionItem { | ||
416 | label: "global_allocator", | ||
417 | source_range: [20; 20), | ||
418 | delete: [20; 20), | ||
419 | insert: "global_allocator", | ||
420 | kind: Attribute, | ||
421 | }, | ||
422 | CompletionItem { | ||
423 | label: "ignore", | ||
424 | source_range: [20; 20), | ||
425 | delete: [20; 20), | ||
426 | insert: "ignore(${0:lint})", | ||
427 | kind: Attribute, | ||
428 | }, | ||
429 | CompletionItem { | ||
430 | label: "inline", | ||
431 | source_range: [20; 20), | ||
432 | delete: [20; 20), | ||
433 | insert: "inline(${0:lint})", | ||
434 | kind: Attribute, | ||
435 | }, | ||
436 | CompletionItem { | ||
437 | label: "link", | ||
438 | source_range: [20; 20), | ||
439 | delete: [20; 20), | ||
440 | insert: "link", | ||
441 | kind: Attribute, | ||
442 | }, | ||
443 | CompletionItem { | ||
444 | label: "link_name", | ||
445 | source_range: [20; 20), | ||
446 | delete: [20; 20), | ||
447 | insert: "link_name = \"${0:symbol_name}\"", | ||
448 | kind: Attribute, | ||
449 | }, | ||
450 | CompletionItem { | ||
451 | label: "macro_export", | ||
452 | source_range: [20; 20), | ||
453 | delete: [20; 20), | ||
454 | insert: "macro_export", | ||
455 | kind: Attribute, | ||
456 | }, | ||
457 | CompletionItem { | ||
458 | label: "macro_use", | ||
459 | source_range: [20; 20), | ||
460 | delete: [20; 20), | ||
461 | insert: "macro_use", | ||
462 | kind: Attribute, | ||
463 | }, | ||
464 | CompletionItem { | ||
465 | label: "must_use", | ||
466 | source_range: [20; 20), | ||
467 | delete: [20; 20), | ||
468 | insert: "must_use = \"${0:reason}\"", | ||
469 | kind: Attribute, | ||
470 | }, | ||
471 | CompletionItem { | ||
472 | label: "no_mangle", | ||
473 | source_range: [20; 20), | ||
474 | delete: [20; 20), | ||
475 | insert: "no_mangle", | ||
476 | kind: Attribute, | ||
477 | }, | ||
478 | CompletionItem { | ||
479 | label: "no_std", | ||
480 | source_range: [20; 20), | ||
481 | delete: [20; 20), | ||
482 | insert: "no_std", | ||
483 | kind: Attribute, | ||
484 | }, | ||
485 | CompletionItem { | ||
486 | label: "non_exhaustive", | ||
487 | source_range: [20; 20), | ||
488 | delete: [20; 20), | ||
489 | insert: "non_exhaustive", | ||
490 | kind: Attribute, | ||
491 | }, | ||
492 | CompletionItem { | ||
493 | label: "panic_handler", | ||
494 | source_range: [20; 20), | ||
495 | delete: [20; 20), | ||
496 | insert: "panic_handler", | ||
497 | kind: Attribute, | ||
498 | }, | ||
499 | CompletionItem { | ||
500 | label: "path", | ||
501 | source_range: [20; 20), | ||
502 | delete: [20; 20), | ||
503 | insert: "path =\"${0:path}\"", | ||
504 | kind: Attribute, | ||
505 | }, | ||
506 | CompletionItem { | ||
507 | label: "proc_macro", | ||
508 | source_range: [20; 20), | ||
509 | delete: [20; 20), | ||
510 | insert: "proc_macro", | ||
511 | kind: Attribute, | ||
512 | }, | ||
513 | CompletionItem { | ||
514 | label: "proc_macro_attribute", | ||
515 | source_range: [20; 20), | ||
516 | delete: [20; 20), | ||
517 | insert: "proc_macro_attribute", | ||
518 | kind: Attribute, | ||
519 | }, | ||
520 | CompletionItem { | ||
521 | label: "proc_macro_derive", | ||
522 | source_range: [20; 20), | ||
523 | delete: [20; 20), | ||
524 | insert: "proc_macro_derive(${0:Trait})", | ||
525 | kind: Attribute, | ||
526 | }, | ||
527 | CompletionItem { | ||
528 | label: "recursion_limit", | ||
529 | source_range: [20; 20), | ||
530 | delete: [20; 20), | ||
531 | insert: "recursion_limit = ${0:128}", | ||
532 | kind: Attribute, | ||
533 | }, | ||
534 | CompletionItem { | ||
535 | label: "repr", | ||
536 | source_range: [20; 20), | ||
537 | delete: [20; 20), | ||
538 | insert: "repr(${0:C})", | ||
539 | kind: Attribute, | ||
540 | }, | ||
541 | CompletionItem { | ||
542 | label: "should_panic", | ||
543 | source_range: [20; 20), | ||
544 | delete: [20; 20), | ||
545 | insert: "expected = \"${0:reason}\"", | ||
546 | kind: Attribute, | ||
547 | }, | ||
548 | CompletionItem { | ||
549 | label: "target_feature", | ||
550 | source_range: [20; 20), | ||
551 | delete: [20; 20), | ||
552 | insert: "target_feature = \"${0:feature}\"", | ||
553 | kind: Attribute, | ||
554 | }, | ||
555 | CompletionItem { | ||
556 | label: "test", | ||
557 | source_range: [20; 20), | ||
558 | delete: [20; 20), | ||
559 | insert: "test", | ||
560 | kind: Attribute, | ||
561 | }, | ||
562 | CompletionItem { | ||
563 | label: "used", | ||
564 | source_range: [20; 20), | ||
565 | delete: [20; 20), | ||
566 | insert: "used", | ||
567 | kind: Attribute, | ||
568 | }, | ||
569 | CompletionItem { | ||
570 | label: "warn", | ||
571 | source_range: [20; 20), | ||
572 | delete: [20; 20), | ||
573 | insert: "warn(${0:lint})", | ||
574 | kind: Attribute, | ||
575 | }, | ||
576 | CompletionItem { | ||
577 | label: "windows_subsystem", | ||
578 | source_range: [20; 20), | ||
579 | delete: [20; 20), | ||
580 | insert: "windows_subsystem = \"${0:subsystem}\"", | ||
581 | kind: Attribute, | ||
582 | }, | ||
583 | ] | ||
584 | "### | ||
585 | ); | ||
586 | } | ||
587 | } | ||
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index f433faef3..b93153b48 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs | |||
@@ -2,9 +2,11 @@ | |||
2 | 2 | ||
3 | use hir::{HasVisibility, Type}; | 3 | use hir::{HasVisibility, Type}; |
4 | 4 | ||
5 | use crate::completion::completion_item::CompletionKind; | ||
6 | use crate::{ | 5 | use crate::{ |
7 | completion::{completion_context::CompletionContext, completion_item::Completions}, | 6 | completion::{ |
7 | completion_context::CompletionContext, | ||
8 | completion_item::{CompletionKind, Completions}, | ||
9 | }, | ||
8 | CompletionItem, | 10 | CompletionItem, |
9 | }; | 11 | }; |
10 | use rustc_hash::FxHashSet; | 12 | use rustc_hash::FxHashSet; |
diff --git a/crates/ra_ide/src/completion/complete_keyword.rs b/crates/ra_ide/src/completion/complete_keyword.rs index 38f9c34e7..adefb290e 100644 --- a/crates/ra_ide/src/completion/complete_keyword.rs +++ b/crates/ra_ide/src/completion/complete_keyword.rs | |||
@@ -42,10 +42,14 @@ pub(super) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionC | |||
42 | } | 42 | } |
43 | 43 | ||
44 | fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { | 44 | fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { |
45 | CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) | 45 | let res = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw) |
46 | .kind(CompletionItemKind::Keyword) | 46 | .kind(CompletionItemKind::Keyword); |
47 | .insert_snippet(snippet) | 47 | |
48 | .build() | 48 | match ctx.config.snippet_cap { |
49 | Some(cap) => res.insert_snippet(cap, snippet), | ||
50 | _ => res.insert_text(if snippet.contains('$') { kw } else { snippet }), | ||
51 | } | ||
52 | .build() | ||
49 | } | 53 | } |
50 | 54 | ||
51 | pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { | 55 | pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { |
diff --git a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs index 270e96df0..6000106d0 100644 --- a/crates/ra_ide/src/completion/complete_macro_in_item_position.rs +++ b/crates/ra_ide/src/completion/complete_macro_in_item_position.rs | |||
@@ -41,7 +41,7 @@ mod tests { | |||
41 | @r###" | 41 | @r###" |
42 | [ | 42 | [ |
43 | CompletionItem { | 43 | CompletionItem { |
44 | label: "foo!", | 44 | label: "foo!(…)", |
45 | source_range: [46; 46), | 45 | source_range: [46; 46), |
46 | delete: [46; 46), | 46 | delete: [46; 46), |
47 | insert: "foo!($0)", | 47 | insert: "foo!($0)", |
@@ -81,7 +81,7 @@ mod tests { | |||
81 | @r###" | 81 | @r###" |
82 | [ | 82 | [ |
83 | CompletionItem { | 83 | CompletionItem { |
84 | label: "vec!", | 84 | label: "vec![…]", |
85 | source_range: [280; 280), | 85 | source_range: [280; 280), |
86 | delete: [280; 280), | 86 | delete: [280; 280), |
87 | insert: "vec![$0]", | 87 | insert: "vec![$0]", |
@@ -118,7 +118,7 @@ mod tests { | |||
118 | @r###" | 118 | @r###" |
119 | [ | 119 | [ |
120 | CompletionItem { | 120 | CompletionItem { |
121 | label: "foo!", | 121 | label: "foo! {…}", |
122 | source_range: [163; 163), | 122 | source_range: [163; 163), |
123 | delete: [163; 163), | 123 | delete: [163; 163), |
124 | insert: "foo! {$0}", | 124 | insert: "foo! {$0}", |
diff --git a/crates/ra_ide/src/completion/complete_pattern.rs b/crates/ra_ide/src/completion/complete_pattern.rs index a8b4ce114..218829b10 100644 --- a/crates/ra_ide/src/completion/complete_pattern.rs +++ b/crates/ra_ide/src/completion/complete_pattern.rs | |||
@@ -125,7 +125,7 @@ mod tests { | |||
125 | kind: Enum, | 125 | kind: Enum, |
126 | }, | 126 | }, |
127 | CompletionItem { | 127 | CompletionItem { |
128 | label: "m!", | 128 | label: "m!(…)", |
129 | source_range: [151; 151), | 129 | source_range: [151; 151), |
130 | delete: [151; 151), | 130 | delete: [151; 151), |
131 | insert: "m!($0)", | 131 | insert: "m!($0)", |
diff --git a/crates/ra_ide/src/completion/complete_postfix.rs b/crates/ra_ide/src/completion/complete_postfix.rs index 29c2881c6..8d397b0fe 100644 --- a/crates/ra_ide/src/completion/complete_postfix.rs +++ b/crates/ra_ide/src/completion/complete_postfix.rs | |||
@@ -6,6 +6,7 @@ use ra_syntax::{ | |||
6 | }; | 6 | }; |
7 | use ra_text_edit::TextEdit; | 7 | use ra_text_edit::TextEdit; |
8 | 8 | ||
9 | use super::completion_config::SnippetCap; | ||
9 | use crate::{ | 10 | use crate::{ |
10 | completion::{ | 11 | completion::{ |
11 | completion_context::CompletionContext, | 12 | completion_context::CompletionContext, |
@@ -32,9 +33,15 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
32 | None => return, | 33 | None => return, |
33 | }; | 34 | }; |
34 | 35 | ||
36 | let cap = match ctx.config.snippet_cap { | ||
37 | Some(it) => it, | ||
38 | None => return, | ||
39 | }; | ||
40 | |||
35 | if receiver_ty.is_bool() || receiver_ty.is_unknown() { | 41 | if receiver_ty.is_bool() || receiver_ty.is_unknown() { |
36 | postfix_snippet( | 42 | postfix_snippet( |
37 | ctx, | 43 | ctx, |
44 | cap, | ||
38 | &dot_receiver, | 45 | &dot_receiver, |
39 | "if", | 46 | "if", |
40 | "if expr {}", | 47 | "if expr {}", |
@@ -43,6 +50,7 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
43 | .add_to(acc); | 50 | .add_to(acc); |
44 | postfix_snippet( | 51 | postfix_snippet( |
45 | ctx, | 52 | ctx, |
53 | cap, | ||
46 | &dot_receiver, | 54 | &dot_receiver, |
47 | "while", | 55 | "while", |
48 | "while expr {}", | 56 | "while expr {}", |
@@ -52,11 +60,20 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
52 | } | 60 | } |
53 | 61 | ||
54 | // !&&&42 is a compiler error, ergo process it before considering the references | 62 | // !&&&42 is a compiler error, ergo process it before considering the references |
55 | postfix_snippet(ctx, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text)).add_to(acc); | 63 | postfix_snippet(ctx, cap, &dot_receiver, "not", "!expr", &format!("!{}", receiver_text)) |
64 | .add_to(acc); | ||
56 | 65 | ||
57 | postfix_snippet(ctx, &dot_receiver, "ref", "&expr", &format!("&{}", receiver_text)).add_to(acc); | 66 | postfix_snippet(ctx, cap, &dot_receiver, "ref", "&expr", &format!("&{}", receiver_text)) |
58 | postfix_snippet(ctx, &dot_receiver, "refm", "&mut expr", &format!("&mut {}", receiver_text)) | ||
59 | .add_to(acc); | 67 | .add_to(acc); |
68 | postfix_snippet( | ||
69 | ctx, | ||
70 | cap, | ||
71 | &dot_receiver, | ||
72 | "refm", | ||
73 | "&mut expr", | ||
74 | &format!("&mut {}", receiver_text), | ||
75 | ) | ||
76 | .add_to(acc); | ||
60 | 77 | ||
61 | // The rest of the postfix completions create an expression that moves an argument, | 78 | // The rest of the postfix completions create an expression that moves an argument, |
62 | // so it's better to consider references now to avoid breaking the compilation | 79 | // so it's better to consider references now to avoid breaking the compilation |
@@ -66,6 +83,7 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
66 | 83 | ||
67 | postfix_snippet( | 84 | postfix_snippet( |
68 | ctx, | 85 | ctx, |
86 | cap, | ||
69 | &dot_receiver, | 87 | &dot_receiver, |
70 | "match", | 88 | "match", |
71 | "match expr {}", | 89 | "match expr {}", |
@@ -75,6 +93,7 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
75 | 93 | ||
76 | postfix_snippet( | 94 | postfix_snippet( |
77 | ctx, | 95 | ctx, |
96 | cap, | ||
78 | &dot_receiver, | 97 | &dot_receiver, |
79 | "box", | 98 | "box", |
80 | "Box::new(expr)", | 99 | "Box::new(expr)", |
@@ -82,8 +101,15 @@ pub(super) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { | |||
82 | ) | 101 | ) |
83 | .add_to(acc); | 102 | .add_to(acc); |
84 | 103 | ||
85 | postfix_snippet(ctx, &dot_receiver, "dbg", "dbg!(expr)", &format!("dbg!({})", receiver_text)) | 104 | postfix_snippet( |
86 | .add_to(acc); | 105 | ctx, |
106 | cap, | ||
107 | &dot_receiver, | ||
108 | "dbg", | ||
109 | "dbg!(expr)", | ||
110 | &format!("dbg!({})", receiver_text), | ||
111 | ) | ||
112 | .add_to(acc); | ||
87 | } | 113 | } |
88 | 114 | ||
89 | fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String { | 115 | fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String { |
@@ -108,6 +134,7 @@ fn include_references(initial_element: &ast::Expr) -> ast::Expr { | |||
108 | 134 | ||
109 | fn postfix_snippet( | 135 | fn postfix_snippet( |
110 | ctx: &CompletionContext, | 136 | ctx: &CompletionContext, |
137 | cap: SnippetCap, | ||
111 | receiver: &ast::Expr, | 138 | receiver: &ast::Expr, |
112 | label: &str, | 139 | label: &str, |
113 | detail: &str, | 140 | detail: &str, |
@@ -121,7 +148,7 @@ fn postfix_snippet( | |||
121 | }; | 148 | }; |
122 | CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label) | 149 | CompletionItem::new(CompletionKind::Postfix, ctx.source_range(), label) |
123 | .detail(detail) | 150 | .detail(detail) |
124 | .snippet_edit(edit) | 151 | .snippet_edit(cap, edit) |
125 | } | 152 | } |
126 | 153 | ||
127 | #[cfg(test)] | 154 | #[cfg(test)] |
diff --git a/crates/ra_ide/src/completion/complete_qualified_path.rs b/crates/ra_ide/src/completion/complete_qualified_path.rs index d98523406..5a5139e14 100644 --- a/crates/ra_ide/src/completion/complete_qualified_path.rs +++ b/crates/ra_ide/src/completion/complete_qualified_path.rs | |||
@@ -57,9 +57,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
57 | } | 57 | } |
58 | match item { | 58 | match item { |
59 | hir::AssocItem::Function(func) => { | 59 | hir::AssocItem::Function(func) => { |
60 | if !func.has_self_param(ctx.db) { | 60 | acc.add_function(ctx, func, None); |
61 | acc.add_function(ctx, func, None); | ||
62 | } | ||
63 | } | 61 | } |
64 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | 62 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), |
65 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | 63 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), |
@@ -86,9 +84,7 @@ pub(super) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
86 | } | 84 | } |
87 | match item { | 85 | match item { |
88 | hir::AssocItem::Function(func) => { | 86 | hir::AssocItem::Function(func) => { |
89 | if !func.has_self_param(ctx.db) { | 87 | acc.add_function(ctx, func, None); |
90 | acc.add_function(ctx, func, None); | ||
91 | } | ||
92 | } | 88 | } |
93 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), | 89 | hir::AssocItem::Const(ct) => acc.add_const(ctx, ct), |
94 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), | 90 | hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty), |
@@ -483,6 +479,42 @@ mod tests { | |||
483 | } | 479 | } |
484 | 480 | ||
485 | #[test] | 481 | #[test] |
482 | fn completes_struct_associated_method_with_self() { | ||
483 | assert_debug_snapshot!( | ||
484 | do_reference_completion( | ||
485 | " | ||
486 | //- /lib.rs | ||
487 | /// A Struct | ||
488 | struct S; | ||
489 | |||
490 | impl S { | ||
491 | /// An associated method | ||
492 | fn m(&self) { } | ||
493 | } | ||
494 | |||
495 | fn foo() { let _ = S::<|> } | ||
496 | " | ||
497 | ), | ||
498 | @r###" | ||
499 | [ | ||
500 | CompletionItem { | ||
501 | label: "m()", | ||
502 | source_range: [105; 105), | ||
503 | delete: [105; 105), | ||
504 | insert: "m()$0", | ||
505 | kind: Method, | ||
506 | lookup: "m", | ||
507 | detail: "fn m(&self)", | ||
508 | documentation: Documentation( | ||
509 | "An associated method", | ||
510 | ), | ||
511 | }, | ||
512 | ] | ||
513 | "### | ||
514 | ); | ||
515 | } | ||
516 | |||
517 | #[test] | ||
486 | fn completes_struct_associated_const() { | 518 | fn completes_struct_associated_const() { |
487 | assert_debug_snapshot!( | 519 | assert_debug_snapshot!( |
488 | do_reference_completion( | 520 | do_reference_completion( |
@@ -869,7 +901,7 @@ mod tests { | |||
869 | @r###" | 901 | @r###" |
870 | [ | 902 | [ |
871 | CompletionItem { | 903 | CompletionItem { |
872 | label: "foo!", | 904 | label: "foo!(…)", |
873 | source_range: [179; 179), | 905 | source_range: [179; 179), |
874 | delete: [179; 179), | 906 | delete: [179; 179), |
875 | insert: "foo!($0)", | 907 | insert: "foo!($0)", |
diff --git a/crates/ra_ide/src/completion/complete_snippet.rs b/crates/ra_ide/src/completion/complete_snippet.rs index f731e9b9a..4bccfbfed 100644 --- a/crates/ra_ide/src/completion/complete_snippet.rs +++ b/crates/ra_ide/src/completion/complete_snippet.rs | |||
@@ -1,13 +1,13 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use crate::completion::{ | 3 | use crate::completion::{ |
4 | completion_item::Builder, CompletionContext, CompletionItem, CompletionItemKind, | 4 | completion_config::SnippetCap, completion_item::Builder, CompletionContext, CompletionItem, |
5 | CompletionKind, Completions, | 5 | CompletionItemKind, CompletionKind, Completions, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | fn snippet(ctx: &CompletionContext, label: &str, snippet: &str) -> Builder { | 8 | fn snippet(ctx: &CompletionContext, cap: SnippetCap, label: &str, snippet: &str) -> Builder { |
9 | CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label) | 9 | CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), label) |
10 | .insert_snippet(snippet) | 10 | .insert_snippet(cap, snippet) |
11 | .kind(CompletionItemKind::Snippet) | 11 | .kind(CompletionItemKind::Snippet) |
12 | } | 12 | } |
13 | 13 | ||
@@ -15,17 +15,27 @@ pub(super) fn complete_expr_snippet(acc: &mut Completions, ctx: &CompletionConte | |||
15 | if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) { | 15 | if !(ctx.is_trivial_path && ctx.function_syntax.is_some()) { |
16 | return; | 16 | return; |
17 | } | 17 | } |
18 | let cap = match ctx.config.snippet_cap { | ||
19 | Some(it) => it, | ||
20 | None => return, | ||
21 | }; | ||
18 | 22 | ||
19 | snippet(ctx, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc); | 23 | snippet(ctx, cap, "pd", "eprintln!(\"$0 = {:?}\", $0);").add_to(acc); |
20 | snippet(ctx, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc); | 24 | snippet(ctx, cap, "ppd", "eprintln!(\"$0 = {:#?}\", $0);").add_to(acc); |
21 | } | 25 | } |
22 | 26 | ||
23 | pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) { | 27 | pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) { |
24 | if !ctx.is_new_item { | 28 | if !ctx.is_new_item { |
25 | return; | 29 | return; |
26 | } | 30 | } |
31 | let cap = match ctx.config.snippet_cap { | ||
32 | Some(it) => it, | ||
33 | None => return, | ||
34 | }; | ||
35 | |||
27 | snippet( | 36 | snippet( |
28 | ctx, | 37 | ctx, |
38 | cap, | ||
29 | "Test function", | 39 | "Test function", |
30 | "\ | 40 | "\ |
31 | #[test] | 41 | #[test] |
@@ -36,8 +46,8 @@ fn ${1:feature}() { | |||
36 | .lookup_by("tfn") | 46 | .lookup_by("tfn") |
37 | .add_to(acc); | 47 | .add_to(acc); |
38 | 48 | ||
39 | snippet(ctx, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc); | 49 | snippet(ctx, cap, "macro_rules", "macro_rules! $1 {\n\t($2) => {\n\t\t$0\n\t};\n}").add_to(acc); |
40 | snippet(ctx, "pub(crate)", "pub(crate) $0").add_to(acc); | 50 | snippet(ctx, cap, "pub(crate)", "pub(crate) $0").add_to(acc); |
41 | } | 51 | } |
42 | 52 | ||
43 | #[cfg(test)] | 53 | #[cfg(test)] |
diff --git a/crates/ra_ide/src/completion/complete_trait_impl.rs b/crates/ra_ide/src/completion/complete_trait_impl.rs index 2ec0e7ce9..c39943252 100644 --- a/crates/ra_ide/src/completion/complete_trait_impl.rs +++ b/crates/ra_ide/src/completion/complete_trait_impl.rs | |||
@@ -122,7 +122,7 @@ fn add_function_impl( | |||
122 | ctx: &CompletionContext, | 122 | ctx: &CompletionContext, |
123 | func: &hir::Function, | 123 | func: &hir::Function, |
124 | ) { | 124 | ) { |
125 | let display = FunctionSignature::from_hir(ctx.db, *func); | 125 | let signature = FunctionSignature::from_hir(ctx.db, *func); |
126 | 126 | ||
127 | let fn_name = func.name(ctx.db).to_string(); | 127 | let fn_name = func.name(ctx.db).to_string(); |
128 | 128 | ||
@@ -141,12 +141,20 @@ fn add_function_impl( | |||
141 | } else { | 141 | } else { |
142 | CompletionItemKind::Function | 142 | CompletionItemKind::Function |
143 | }; | 143 | }; |
144 | |||
145 | let snippet = format!("{} {{\n $0\n}}", display); | ||
146 | |||
147 | let range = TextRange::from_to(fn_def_node.text_range().start(), ctx.source_range().end()); | 144 | let range = TextRange::from_to(fn_def_node.text_range().start(), ctx.source_range().end()); |
148 | 145 | ||
149 | builder.snippet_edit(TextEdit::replace(range, snippet)).kind(completion_kind).add_to(acc); | 146 | match ctx.config.snippet_cap { |
147 | Some(cap) => { | ||
148 | let snippet = format!("{} {{\n $0\n}}", signature); | ||
149 | builder.snippet_edit(cap, TextEdit::replace(range, snippet)) | ||
150 | } | ||
151 | None => { | ||
152 | let header = format!("{} {{", signature); | ||
153 | builder.text_edit(TextEdit::replace(range, header)) | ||
154 | } | ||
155 | } | ||
156 | .kind(completion_kind) | ||
157 | .add_to(acc); | ||
150 | } | 158 | } |
151 | 159 | ||
152 | fn add_type_alias_impl( | 160 | fn add_type_alias_impl( |
diff --git a/crates/ra_ide/src/completion/complete_unqualified_path.rs b/crates/ra_ide/src/completion/complete_unqualified_path.rs index ad5fdcc4e..638f86eda 100644 --- a/crates/ra_ide/src/completion/complete_unqualified_path.rs +++ b/crates/ra_ide/src/completion/complete_unqualified_path.rs | |||
@@ -4,20 +4,23 @@ use hir::ScopeDef; | |||
4 | use test_utils::tested_by; | 4 | use test_utils::tested_by; |
5 | 5 | ||
6 | use crate::completion::{CompletionContext, Completions}; | 6 | use crate::completion::{CompletionContext, Completions}; |
7 | use hir::{Adt, ModuleDef}; | ||
7 | use ra_syntax::AstNode; | 8 | use ra_syntax::AstNode; |
8 | 9 | ||
9 | pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { | 10 | pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { |
10 | if !ctx.is_trivial_path { | 11 | if (!ctx.is_trivial_path && !ctx.is_pat_binding_or_const) |
11 | return; | ||
12 | } | ||
13 | |||
14 | if ctx.is_pat_binding_or_const | ||
15 | || ctx.record_lit_syntax.is_some() | 12 | || ctx.record_lit_syntax.is_some() |
16 | || ctx.record_pat_syntax.is_some() | 13 | || ctx.record_pat_syntax.is_some() |
17 | { | 14 | { |
18 | return; | 15 | return; |
19 | } | 16 | } |
20 | 17 | ||
18 | complete_enum_variants(acc, ctx); | ||
19 | |||
20 | if ctx.is_pat_binding_or_const { | ||
21 | return; | ||
22 | } | ||
23 | |||
21 | ctx.scope().process_all_names(&mut |name, res| { | 24 | ctx.scope().process_all_names(&mut |name, res| { |
22 | if ctx.use_item_syntax.is_some() { | 25 | if ctx.use_item_syntax.is_some() { |
23 | if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { | 26 | if let (ScopeDef::Unknown, Some(name_ref)) = (&res, &ctx.name_ref_syntax) { |
@@ -31,6 +34,24 @@ pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC | |||
31 | }); | 34 | }); |
32 | } | 35 | } |
33 | 36 | ||
37 | fn complete_enum_variants(acc: &mut Completions, ctx: &CompletionContext) { | ||
38 | if let Some(ty) = ctx.expected_type_of(&ctx.token.parent()) { | ||
39 | if let Some(Adt::Enum(enum_data)) = ty.as_adt() { | ||
40 | let variants = enum_data.variants(ctx.db); | ||
41 | let module = enum_data.module(ctx.db); | ||
42 | for variant in variants { | ||
43 | if let Some(path) = module.find_use_path(ctx.db, ModuleDef::from(variant)) { | ||
44 | // Variants with trivial paths are already added by the existing completion logic, | ||
45 | // so we should avoid adding these twice | ||
46 | if path.segments.len() > 1 { | ||
47 | acc.add_enum_variant(ctx, variant, Some(path.to_string())); | ||
48 | } | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | } | ||
54 | |||
34 | #[cfg(test)] | 55 | #[cfg(test)] |
35 | mod tests { | 56 | mod tests { |
36 | use insta::assert_debug_snapshot; | 57 | use insta::assert_debug_snapshot; |
@@ -82,7 +103,7 @@ mod tests { | |||
82 | } | 103 | } |
83 | " | 104 | " |
84 | ), | 105 | ), |
85 | @r###"[]"### | 106 | @"[]" |
86 | ); | 107 | ); |
87 | } | 108 | } |
88 | 109 | ||
@@ -712,7 +733,7 @@ mod tests { | |||
712 | @r###" | 733 | @r###" |
713 | [ | 734 | [ |
714 | CompletionItem { | 735 | CompletionItem { |
715 | label: "bar!", | 736 | label: "bar!(…)", |
716 | source_range: [252; 252), | 737 | source_range: [252; 252), |
717 | delete: [252; 252), | 738 | delete: [252; 252), |
718 | insert: "bar!($0)", | 739 | insert: "bar!($0)", |
@@ -720,7 +741,7 @@ mod tests { | |||
720 | detail: "macro_rules! bar", | 741 | detail: "macro_rules! bar", |
721 | }, | 742 | }, |
722 | CompletionItem { | 743 | CompletionItem { |
723 | label: "baz!", | 744 | label: "baz!(…)", |
724 | source_range: [252; 252), | 745 | source_range: [252; 252), |
725 | delete: [252; 252), | 746 | delete: [252; 252), |
726 | insert: "baz!($0)", | 747 | insert: "baz!($0)", |
@@ -728,7 +749,7 @@ mod tests { | |||
728 | detail: "#[macro_export]\nmacro_rules! baz", | 749 | detail: "#[macro_export]\nmacro_rules! baz", |
729 | }, | 750 | }, |
730 | CompletionItem { | 751 | CompletionItem { |
731 | label: "foo!", | 752 | label: "foo!(…)", |
732 | source_range: [252; 252), | 753 | source_range: [252; 252), |
733 | delete: [252; 252), | 754 | delete: [252; 252), |
734 | insert: "foo!($0)", | 755 | insert: "foo!($0)", |
@@ -781,7 +802,7 @@ mod tests { | |||
781 | @r###" | 802 | @r###" |
782 | [ | 803 | [ |
783 | CompletionItem { | 804 | CompletionItem { |
784 | label: "foo!", | 805 | label: "foo!(…)", |
785 | source_range: [49; 49), | 806 | source_range: [49; 49), |
786 | delete: [49; 49), | 807 | delete: [49; 49), |
787 | insert: "foo!($0)", | 808 | insert: "foo!($0)", |
@@ -820,7 +841,7 @@ mod tests { | |||
820 | @r###" | 841 | @r###" |
821 | [ | 842 | [ |
822 | CompletionItem { | 843 | CompletionItem { |
823 | label: "foo!", | 844 | label: "foo!(…)", |
824 | source_range: [57; 57), | 845 | source_range: [57; 57), |
825 | delete: [57; 57), | 846 | delete: [57; 57), |
826 | insert: "foo!($0)", | 847 | insert: "foo!($0)", |
@@ -859,7 +880,7 @@ mod tests { | |||
859 | @r###" | 880 | @r###" |
860 | [ | 881 | [ |
861 | CompletionItem { | 882 | CompletionItem { |
862 | label: "foo!", | 883 | label: "foo!(…)", |
863 | source_range: [50; 50), | 884 | source_range: [50; 50), |
864 | delete: [50; 50), | 885 | delete: [50; 50), |
865 | insert: "foo!($0)", | 886 | insert: "foo!($0)", |
@@ -932,7 +953,7 @@ mod tests { | |||
932 | @r###" | 953 | @r###" |
933 | [ | 954 | [ |
934 | CompletionItem { | 955 | CompletionItem { |
935 | label: "m!", | 956 | label: "m!(…)", |
936 | source_range: [145; 145), | 957 | source_range: [145; 145), |
937 | delete: [145; 145), | 958 | delete: [145; 145), |
938 | insert: "m!($0)", | 959 | insert: "m!($0)", |
@@ -985,7 +1006,7 @@ mod tests { | |||
985 | @r###" | 1006 | @r###" |
986 | [ | 1007 | [ |
987 | CompletionItem { | 1008 | CompletionItem { |
988 | label: "m!", | 1009 | label: "m!(…)", |
989 | source_range: [145; 146), | 1010 | source_range: [145; 146), |
990 | delete: [145; 146), | 1011 | delete: [145; 146), |
991 | insert: "m!($0)", | 1012 | insert: "m!($0)", |
@@ -1038,7 +1059,7 @@ mod tests { | |||
1038 | @r###" | 1059 | @r###" |
1039 | [ | 1060 | [ |
1040 | CompletionItem { | 1061 | CompletionItem { |
1041 | label: "m!", | 1062 | label: "m!(…)", |
1042 | source_range: [145; 146), | 1063 | source_range: [145; 146), |
1043 | delete: [145; 146), | 1064 | delete: [145; 146), |
1044 | insert: "m!($0)", | 1065 | insert: "m!($0)", |
@@ -1109,4 +1130,182 @@ mod tests { | |||
1109 | "### | 1130 | "### |
1110 | ); | 1131 | ); |
1111 | } | 1132 | } |
1133 | #[test] | ||
1134 | fn completes_enum_variant_matcharm() { | ||
1135 | assert_debug_snapshot!( | ||
1136 | do_reference_completion( | ||
1137 | r" | ||
1138 | enum Foo { | ||
1139 | Bar, | ||
1140 | Baz, | ||
1141 | Quux | ||
1142 | } | ||
1143 | |||
1144 | fn main() { | ||
1145 | let foo = Foo::Quux; | ||
1146 | |||
1147 | match foo { | ||
1148 | Qu<|> | ||
1149 | } | ||
1150 | } | ||
1151 | " | ||
1152 | ), | ||
1153 | @r###" | ||
1154 | [ | ||
1155 | CompletionItem { | ||
1156 | label: "Foo", | ||
1157 | source_range: [248; 250), | ||
1158 | delete: [248; 250), | ||
1159 | insert: "Foo", | ||
1160 | kind: Enum, | ||
1161 | }, | ||
1162 | CompletionItem { | ||
1163 | label: "Foo::Bar", | ||
1164 | source_range: [248; 250), | ||
1165 | delete: [248; 250), | ||
1166 | insert: "Foo::Bar", | ||
1167 | kind: EnumVariant, | ||
1168 | detail: "()", | ||
1169 | }, | ||
1170 | CompletionItem { | ||
1171 | label: "Foo::Baz", | ||
1172 | source_range: [248; 250), | ||
1173 | delete: [248; 250), | ||
1174 | insert: "Foo::Baz", | ||
1175 | kind: EnumVariant, | ||
1176 | detail: "()", | ||
1177 | }, | ||
1178 | CompletionItem { | ||
1179 | label: "Foo::Quux", | ||
1180 | source_range: [248; 250), | ||
1181 | delete: [248; 250), | ||
1182 | insert: "Foo::Quux", | ||
1183 | kind: EnumVariant, | ||
1184 | detail: "()", | ||
1185 | }, | ||
1186 | ] | ||
1187 | "### | ||
1188 | ) | ||
1189 | } | ||
1190 | |||
1191 | #[test] | ||
1192 | fn completes_enum_variant_iflet() { | ||
1193 | assert_debug_snapshot!( | ||
1194 | do_reference_completion( | ||
1195 | r" | ||
1196 | enum Foo { | ||
1197 | Bar, | ||
1198 | Baz, | ||
1199 | Quux | ||
1200 | } | ||
1201 | |||
1202 | fn main() { | ||
1203 | let foo = Foo::Quux; | ||
1204 | |||
1205 | if let Qu<|> = foo { | ||
1206 | |||
1207 | } | ||
1208 | } | ||
1209 | " | ||
1210 | ), | ||
1211 | @r###" | ||
1212 | [ | ||
1213 | CompletionItem { | ||
1214 | label: "Foo", | ||
1215 | source_range: [219; 221), | ||
1216 | delete: [219; 221), | ||
1217 | insert: "Foo", | ||
1218 | kind: Enum, | ||
1219 | }, | ||
1220 | CompletionItem { | ||
1221 | label: "Foo::Bar", | ||
1222 | source_range: [219; 221), | ||
1223 | delete: [219; 221), | ||
1224 | insert: "Foo::Bar", | ||
1225 | kind: EnumVariant, | ||
1226 | detail: "()", | ||
1227 | }, | ||
1228 | CompletionItem { | ||
1229 | label: "Foo::Baz", | ||
1230 | source_range: [219; 221), | ||
1231 | delete: [219; 221), | ||
1232 | insert: "Foo::Baz", | ||
1233 | kind: EnumVariant, | ||
1234 | detail: "()", | ||
1235 | }, | ||
1236 | CompletionItem { | ||
1237 | label: "Foo::Quux", | ||
1238 | source_range: [219; 221), | ||
1239 | delete: [219; 221), | ||
1240 | insert: "Foo::Quux", | ||
1241 | kind: EnumVariant, | ||
1242 | detail: "()", | ||
1243 | }, | ||
1244 | ] | ||
1245 | "### | ||
1246 | ) | ||
1247 | } | ||
1248 | |||
1249 | #[test] | ||
1250 | fn completes_enum_variant_basic_expr() { | ||
1251 | assert_debug_snapshot!( | ||
1252 | do_reference_completion( | ||
1253 | r" | ||
1254 | enum Foo { | ||
1255 | Bar, | ||
1256 | Baz, | ||
1257 | Quux | ||
1258 | } | ||
1259 | |||
1260 | fn main() { | ||
1261 | let foo: Foo = Q<|> | ||
1262 | } | ||
1263 | " | ||
1264 | ), | ||
1265 | @r###" | ||
1266 | [ | ||
1267 | CompletionItem { | ||
1268 | label: "Foo", | ||
1269 | source_range: [185; 186), | ||
1270 | delete: [185; 186), | ||
1271 | insert: "Foo", | ||
1272 | kind: Enum, | ||
1273 | }, | ||
1274 | CompletionItem { | ||
1275 | label: "Foo::Bar", | ||
1276 | source_range: [185; 186), | ||
1277 | delete: [185; 186), | ||
1278 | insert: "Foo::Bar", | ||
1279 | kind: EnumVariant, | ||
1280 | detail: "()", | ||
1281 | }, | ||
1282 | CompletionItem { | ||
1283 | label: "Foo::Baz", | ||
1284 | source_range: [185; 186), | ||
1285 | delete: [185; 186), | ||
1286 | insert: "Foo::Baz", | ||
1287 | kind: EnumVariant, | ||
1288 | detail: "()", | ||
1289 | }, | ||
1290 | CompletionItem { | ||
1291 | label: "Foo::Quux", | ||
1292 | source_range: [185; 186), | ||
1293 | delete: [185; 186), | ||
1294 | insert: "Foo::Quux", | ||
1295 | kind: EnumVariant, | ||
1296 | detail: "()", | ||
1297 | }, | ||
1298 | CompletionItem { | ||
1299 | label: "main()", | ||
1300 | source_range: [185; 186), | ||
1301 | delete: [185; 186), | ||
1302 | insert: "main()$0", | ||
1303 | kind: Function, | ||
1304 | lookup: "main", | ||
1305 | detail: "fn main()", | ||
1306 | }, | ||
1307 | ] | ||
1308 | "### | ||
1309 | ) | ||
1310 | } | ||
1112 | } | 1311 | } |
diff --git a/crates/ra_ide/src/completion/completion_config.rs b/crates/ra_ide/src/completion/completion_config.rs new file mode 100644 index 000000000..71b49ace8 --- /dev/null +++ b/crates/ra_ide/src/completion/completion_config.rs | |||
@@ -0,0 +1,35 @@ | |||
1 | //! Settings for tweaking completion. | ||
2 | //! | ||
3 | //! The fun thing here is `SnippetCap` -- this type can only be created in this | ||
4 | //! module, and we use to statically check that we only produce snippet | ||
5 | //! completions if we are allowed to. | ||
6 | |||
7 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
8 | pub struct CompletionConfig { | ||
9 | pub enable_postfix_completions: bool, | ||
10 | pub add_call_parenthesis: bool, | ||
11 | pub add_call_argument_snippets: bool, | ||
12 | pub snippet_cap: Option<SnippetCap>, | ||
13 | } | ||
14 | |||
15 | impl CompletionConfig { | ||
16 | pub fn allow_snippets(&mut self, yes: bool) { | ||
17 | self.snippet_cap = if yes { Some(SnippetCap { _private: () }) } else { None } | ||
18 | } | ||
19 | } | ||
20 | |||
21 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] | ||
22 | pub struct SnippetCap { | ||
23 | _private: (), | ||
24 | } | ||
25 | |||
26 | impl Default for CompletionConfig { | ||
27 | fn default() -> Self { | ||
28 | CompletionConfig { | ||
29 | enable_postfix_completions: true, | ||
30 | add_call_parenthesis: true, | ||
31 | add_call_argument_snippets: true, | ||
32 | snippet_cap: Some(SnippetCap { _private: () }), | ||
33 | } | ||
34 | } | ||
35 | } | ||
diff --git a/crates/ra_ide/src/completion/completion_context.rs b/crates/ra_ide/src/completion/completion_context.rs index 8b3401595..37880448a 100644 --- a/crates/ra_ide/src/completion/completion_context.rs +++ b/crates/ra_ide/src/completion/completion_context.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{Semantics, SemanticsScope}; | 3 | use hir::{Semantics, SemanticsScope, Type}; |
4 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
5 | use ra_ide_db::RootDatabase; | 5 | use ra_ide_db::RootDatabase; |
6 | use ra_syntax::{ | 6 | use ra_syntax::{ |
@@ -11,7 +11,7 @@ use ra_syntax::{ | |||
11 | }; | 11 | }; |
12 | use ra_text_edit::AtomTextEdit; | 12 | use ra_text_edit::AtomTextEdit; |
13 | 13 | ||
14 | use crate::{completion::CompletionConfig, FilePosition}; | 14 | use crate::{call_info::ActiveParameter, completion::CompletionConfig, FilePosition}; |
15 | 15 | ||
16 | /// `CompletionContext` is created early during completion to figure out, where | 16 | /// `CompletionContext` is created early during completion to figure out, where |
17 | /// exactly is the cursor, syntax-wise. | 17 | /// exactly is the cursor, syntax-wise. |
@@ -31,7 +31,10 @@ pub(crate) struct CompletionContext<'a> { | |||
31 | pub(super) use_item_syntax: Option<ast::UseItem>, | 31 | pub(super) use_item_syntax: Option<ast::UseItem>, |
32 | pub(super) record_lit_syntax: Option<ast::RecordLit>, | 32 | pub(super) record_lit_syntax: Option<ast::RecordLit>, |
33 | pub(super) record_pat_syntax: Option<ast::RecordPat>, | 33 | pub(super) record_pat_syntax: Option<ast::RecordPat>, |
34 | pub(super) record_field_syntax: Option<ast::RecordField>, | ||
34 | pub(super) impl_def: Option<ast::ImplDef>, | 35 | pub(super) impl_def: Option<ast::ImplDef>, |
36 | /// FIXME: `ActiveParameter` is string-based, which is very wrong | ||
37 | pub(super) active_parameter: Option<ActiveParameter>, | ||
35 | pub(super) is_param: bool, | 38 | pub(super) is_param: bool, |
36 | /// If a name-binding or reference to a const in a pattern. | 39 | /// If a name-binding or reference to a const in a pattern. |
37 | /// Irrefutable patterns (like let) are excluded. | 40 | /// Irrefutable patterns (like let) are excluded. |
@@ -54,6 +57,7 @@ pub(crate) struct CompletionContext<'a> { | |||
54 | pub(super) is_macro_call: bool, | 57 | pub(super) is_macro_call: bool, |
55 | pub(super) is_path_type: bool, | 58 | pub(super) is_path_type: bool, |
56 | pub(super) has_type_args: bool, | 59 | pub(super) has_type_args: bool, |
60 | pub(super) is_attribute: bool, | ||
57 | } | 61 | } |
58 | 62 | ||
59 | impl<'a> CompletionContext<'a> { | 63 | impl<'a> CompletionContext<'a> { |
@@ -94,7 +98,9 @@ impl<'a> CompletionContext<'a> { | |||
94 | use_item_syntax: None, | 98 | use_item_syntax: None, |
95 | record_lit_syntax: None, | 99 | record_lit_syntax: None, |
96 | record_pat_syntax: None, | 100 | record_pat_syntax: None, |
101 | record_field_syntax: None, | ||
97 | impl_def: None, | 102 | impl_def: None, |
103 | active_parameter: ActiveParameter::at(db, position), | ||
98 | is_param: false, | 104 | is_param: false, |
99 | is_pat_binding_or_const: false, | 105 | is_pat_binding_or_const: false, |
100 | is_trivial_path: false, | 106 | is_trivial_path: false, |
@@ -108,6 +114,7 @@ impl<'a> CompletionContext<'a> { | |||
108 | is_path_type: false, | 114 | is_path_type: false, |
109 | has_type_args: false, | 115 | has_type_args: false, |
110 | dot_receiver_is_ambiguous_float_literal: false, | 116 | dot_receiver_is_ambiguous_float_literal: false, |
117 | is_attribute: false, | ||
111 | }; | 118 | }; |
112 | 119 | ||
113 | let mut original_file = original_file.syntax().clone(); | 120 | let mut original_file = original_file.syntax().clone(); |
@@ -168,6 +175,17 @@ impl<'a> CompletionContext<'a> { | |||
168 | self.sema.scope_at_offset(&self.token.parent(), self.offset) | 175 | self.sema.scope_at_offset(&self.token.parent(), self.offset) |
169 | } | 176 | } |
170 | 177 | ||
178 | pub(crate) fn expected_type_of(&self, node: &SyntaxNode) -> Option<Type> { | ||
179 | for ancestor in node.ancestors() { | ||
180 | if let Some(pat) = ast::Pat::cast(ancestor.clone()) { | ||
181 | return self.sema.type_of_pat(&pat); | ||
182 | } else if let Some(expr) = ast::Expr::cast(ancestor) { | ||
183 | return self.sema.type_of_expr(&expr); | ||
184 | } | ||
185 | } | ||
186 | None | ||
187 | } | ||
188 | |||
171 | fn fill( | 189 | fn fill( |
172 | &mut self, | 190 | &mut self, |
173 | original_file: &SyntaxNode, | 191 | original_file: &SyntaxNode, |
@@ -268,6 +286,14 @@ impl<'a> CompletionContext<'a> { | |||
268 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) | 286 | .take_while(|it| it.kind() != SOURCE_FILE && it.kind() != MODULE) |
269 | .find_map(ast::FnDef::cast); | 287 | .find_map(ast::FnDef::cast); |
270 | 288 | ||
289 | self.record_field_syntax = self | ||
290 | .sema | ||
291 | .ancestors_with_macros(self.token.parent()) | ||
292 | .take_while(|it| { | ||
293 | it.kind() != SOURCE_FILE && it.kind() != MODULE && it.kind() != CALL_EXPR | ||
294 | }) | ||
295 | .find_map(ast::RecordField::cast); | ||
296 | |||
271 | let parent = match name_ref.syntax().parent() { | 297 | let parent = match name_ref.syntax().parent() { |
272 | Some(it) => it, | 298 | Some(it) => it, |
273 | None => return, | 299 | None => return, |
@@ -282,6 +308,7 @@ impl<'a> CompletionContext<'a> { | |||
282 | .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) | 308 | .and_then(|it| it.syntax().parent().and_then(ast::CallExpr::cast)) |
283 | .is_some(); | 309 | .is_some(); |
284 | self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); | 310 | self.is_macro_call = path.syntax().parent().and_then(ast::MacroCall::cast).is_some(); |
311 | self.is_attribute = path.syntax().parent().and_then(ast::Attr::cast).is_some(); | ||
285 | 312 | ||
286 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); | 313 | self.is_path_type = path.syntax().parent().and_then(ast::PathType::cast).is_some(); |
287 | self.has_type_args = segment.type_arg_list().is_some(); | 314 | self.has_type_args = segment.type_arg_list().is_some(); |
diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index bc0f1aff5..5936fb8f7 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::fmt; | 3 | use std::fmt; |
4 | 4 | ||
5 | use super::completion_config::SnippetCap; | ||
5 | use hir::Documentation; | 6 | use hir::Documentation; |
6 | use ra_syntax::TextRange; | 7 | use ra_syntax::TextRange; |
7 | use ra_text_edit::TextEdit; | 8 | use ra_text_edit::TextEdit; |
@@ -51,6 +52,9 @@ pub struct CompletionItem { | |||
51 | /// If completing a function call, ask the editor to show parameter popup | 52 | /// If completing a function call, ask the editor to show parameter popup |
52 | /// after completion. | 53 | /// after completion. |
53 | trigger_call_info: bool, | 54 | trigger_call_info: bool, |
55 | |||
56 | /// Score is useful to pre select or display in better order completion items | ||
57 | score: Option<CompletionScore>, | ||
54 | } | 58 | } |
55 | 59 | ||
56 | // We use custom debug for CompletionItem to make `insta`'s diffs more readable. | 60 | // We use custom debug for CompletionItem to make `insta`'s diffs more readable. |
@@ -80,6 +84,9 @@ impl fmt::Debug for CompletionItem { | |||
80 | if self.deprecated { | 84 | if self.deprecated { |
81 | s.field("deprecated", &true); | 85 | s.field("deprecated", &true); |
82 | } | 86 | } |
87 | if let Some(score) = &self.score { | ||
88 | s.field("score", score); | ||
89 | } | ||
83 | if self.trigger_call_info { | 90 | if self.trigger_call_info { |
84 | s.field("trigger_call_info", &true); | 91 | s.field("trigger_call_info", &true); |
85 | } | 92 | } |
@@ -87,6 +94,14 @@ impl fmt::Debug for CompletionItem { | |||
87 | } | 94 | } |
88 | } | 95 | } |
89 | 96 | ||
97 | #[derive(Debug, Clone, Copy)] | ||
98 | pub enum CompletionScore { | ||
99 | /// If only type match | ||
100 | TypeMatch, | ||
101 | /// If type and name match | ||
102 | TypeAndNameMatch, | ||
103 | } | ||
104 | |||
90 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] | 105 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] |
91 | pub enum CompletionItemKind { | 106 | pub enum CompletionItemKind { |
92 | Snippet, | 107 | Snippet, |
@@ -106,6 +121,7 @@ pub enum CompletionItemKind { | |||
106 | Method, | 121 | Method, |
107 | TypeParam, | 122 | TypeParam, |
108 | Macro, | 123 | Macro, |
124 | Attribute, | ||
109 | } | 125 | } |
110 | 126 | ||
111 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | 127 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
@@ -119,6 +135,7 @@ pub(crate) enum CompletionKind { | |||
119 | Snippet, | 135 | Snippet, |
120 | Postfix, | 136 | Postfix, |
121 | BuiltinType, | 137 | BuiltinType, |
138 | Attribute, | ||
122 | } | 139 | } |
123 | 140 | ||
124 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] | 141 | #[derive(Debug, PartialEq, Eq, Copy, Clone)] |
@@ -147,6 +164,7 @@ impl CompletionItem { | |||
147 | text_edit: None, | 164 | text_edit: None, |
148 | deprecated: None, | 165 | deprecated: None, |
149 | trigger_call_info: None, | 166 | trigger_call_info: None, |
167 | score: None, | ||
150 | } | 168 | } |
151 | } | 169 | } |
152 | /// What user sees in pop-up in the UI. | 170 | /// What user sees in pop-up in the UI. |
@@ -175,7 +193,7 @@ impl CompletionItem { | |||
175 | } | 193 | } |
176 | /// What string is used for filtering. | 194 | /// What string is used for filtering. |
177 | pub fn lookup(&self) -> &str { | 195 | pub fn lookup(&self) -> &str { |
178 | self.lookup.as_deref().unwrap_or_else(|| self.label()) | 196 | self.lookup.as_deref().unwrap_or(&self.label) |
179 | } | 197 | } |
180 | 198 | ||
181 | pub fn kind(&self) -> Option<CompletionItemKind> { | 199 | pub fn kind(&self) -> Option<CompletionItemKind> { |
@@ -186,6 +204,10 @@ impl CompletionItem { | |||
186 | self.deprecated | 204 | self.deprecated |
187 | } | 205 | } |
188 | 206 | ||
207 | pub fn score(&self) -> Option<CompletionScore> { | ||
208 | self.score | ||
209 | } | ||
210 | |||
189 | pub fn trigger_call_info(&self) -> bool { | 211 | pub fn trigger_call_info(&self) -> bool { |
190 | self.trigger_call_info | 212 | self.trigger_call_info |
191 | } | 213 | } |
@@ -206,6 +228,7 @@ pub(crate) struct Builder { | |||
206 | text_edit: Option<TextEdit>, | 228 | text_edit: Option<TextEdit>, |
207 | deprecated: Option<bool>, | 229 | deprecated: Option<bool>, |
208 | trigger_call_info: Option<bool>, | 230 | trigger_call_info: Option<bool>, |
231 | score: Option<CompletionScore>, | ||
209 | } | 232 | } |
210 | 233 | ||
211 | impl Builder { | 234 | impl Builder { |
@@ -235,6 +258,7 @@ impl Builder { | |||
235 | completion_kind: self.completion_kind, | 258 | completion_kind: self.completion_kind, |
236 | deprecated: self.deprecated.unwrap_or(false), | 259 | deprecated: self.deprecated.unwrap_or(false), |
237 | trigger_call_info: self.trigger_call_info.unwrap_or(false), | 260 | trigger_call_info: self.trigger_call_info.unwrap_or(false), |
261 | score: self.score, | ||
238 | } | 262 | } |
239 | } | 263 | } |
240 | pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { | 264 | pub(crate) fn lookup_by(mut self, lookup: impl Into<String>) -> Builder { |
@@ -249,7 +273,11 @@ impl Builder { | |||
249 | self.insert_text = Some(insert_text.into()); | 273 | self.insert_text = Some(insert_text.into()); |
250 | self | 274 | self |
251 | } | 275 | } |
252 | pub(crate) fn insert_snippet(mut self, snippet: impl Into<String>) -> Builder { | 276 | pub(crate) fn insert_snippet( |
277 | mut self, | ||
278 | _cap: SnippetCap, | ||
279 | snippet: impl Into<String>, | ||
280 | ) -> Builder { | ||
253 | self.insert_text_format = InsertTextFormat::Snippet; | 281 | self.insert_text_format = InsertTextFormat::Snippet; |
254 | self.insert_text(snippet) | 282 | self.insert_text(snippet) |
255 | } | 283 | } |
@@ -261,7 +289,7 @@ impl Builder { | |||
261 | self.text_edit = Some(edit); | 289 | self.text_edit = Some(edit); |
262 | self | 290 | self |
263 | } | 291 | } |
264 | pub(crate) fn snippet_edit(mut self, edit: TextEdit) -> Builder { | 292 | pub(crate) fn snippet_edit(mut self, _cap: SnippetCap, edit: TextEdit) -> Builder { |
265 | self.insert_text_format = InsertTextFormat::Snippet; | 293 | self.insert_text_format = InsertTextFormat::Snippet; |
266 | self.text_edit(edit) | 294 | self.text_edit(edit) |
267 | } | 295 | } |
@@ -285,6 +313,10 @@ impl Builder { | |||
285 | self.deprecated = Some(deprecated); | 313 | self.deprecated = Some(deprecated); |
286 | self | 314 | self |
287 | } | 315 | } |
316 | pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder { | ||
317 | self.score = Some(score); | ||
318 | self | ||
319 | } | ||
288 | pub(crate) fn trigger_call_info(mut self) -> Builder { | 320 | pub(crate) fn trigger_call_info(mut self) -> Builder { |
289 | self.trigger_call_info = Some(true); | 321 | self.trigger_call_info = Some(true); |
290 | self | 322 | self |
diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 55f75b15a..6a6ddc7bd 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | CompletionKind, Completions, | 11 | CompletionKind, Completions, |
12 | }, | 12 | }, |
13 | display::{const_label, macro_label, type_label, FunctionSignature}, | 13 | display::{const_label, macro_label, type_label, FunctionSignature}, |
14 | RootDatabase, | 14 | CompletionScore, RootDatabase, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | impl Completions { | 17 | impl Completions { |
@@ -22,16 +22,20 @@ impl Completions { | |||
22 | ty: &Type, | 22 | ty: &Type, |
23 | ) { | 23 | ) { |
24 | let is_deprecated = is_deprecated(field, ctx.db); | 24 | let is_deprecated = is_deprecated(field, ctx.db); |
25 | CompletionItem::new( | 25 | let ty = ty.display(ctx.db).to_string(); |
26 | CompletionKind::Reference, | 26 | let name = field.name(ctx.db); |
27 | ctx.source_range(), | 27 | let mut completion_item = |
28 | field.name(ctx.db).to_string(), | 28 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.to_string()) |
29 | ) | 29 | .kind(CompletionItemKind::Field) |
30 | .kind(CompletionItemKind::Field) | 30 | .detail(ty.clone()) |
31 | .detail(ty.display(ctx.db).to_string()) | 31 | .set_documentation(field.docs(ctx.db)) |
32 | .set_documentation(field.docs(ctx.db)) | 32 | .set_deprecated(is_deprecated); |
33 | .set_deprecated(is_deprecated) | 33 | |
34 | .add_to(self); | 34 | if let Some(score) = compute_score(ctx, &ty, &name.to_string()) { |
35 | completion_item = completion_item.set_score(score); | ||
36 | } | ||
37 | |||
38 | completion_item.add_to(self); | ||
35 | } | 39 | } |
36 | 40 | ||
37 | pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &Type) { | 41 | pub(crate) fn add_tuple_field(&mut self, ctx: &CompletionContext, field: usize, ty: &Type) { |
@@ -110,44 +114,23 @@ impl Completions { | |||
110 | 114 | ||
111 | // Add `<>` for generic types | 115 | // Add `<>` for generic types |
112 | if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis { | 116 | if ctx.is_path_type && !ctx.has_type_args && ctx.config.add_call_parenthesis { |
113 | let has_non_default_type_params = match resolution { | 117 | if let Some(cap) = ctx.config.snippet_cap { |
114 | ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db), | 118 | let has_non_default_type_params = match resolution { |
115 | ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db), | 119 | ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db), |
116 | _ => false, | 120 | ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db), |
117 | }; | 121 | _ => false, |
118 | if has_non_default_type_params { | 122 | }; |
119 | tested_by!(inserts_angle_brackets_for_generics); | 123 | if has_non_default_type_params { |
120 | completion_item = completion_item | 124 | tested_by!(inserts_angle_brackets_for_generics); |
121 | .lookup_by(local_name.clone()) | 125 | completion_item = completion_item |
122 | .label(format!("{}<…>", local_name)) | 126 | .lookup_by(local_name.clone()) |
123 | .insert_snippet(format!("{}<$0>", local_name)); | 127 | .label(format!("{}<…>", local_name)) |
124 | } | 128 | .insert_snippet(cap, format!("{}<$0>", local_name)); |
125 | } | ||
126 | |||
127 | completion_item.kind(kind).set_documentation(docs).add_to(self) | ||
128 | } | ||
129 | |||
130 | fn guess_macro_braces(&self, macro_name: &str, docs: &str) -> &'static str { | ||
131 | let mut votes = [0, 0, 0]; | ||
132 | for (idx, s) in docs.match_indices(¯o_name) { | ||
133 | let (before, after) = (&docs[..idx], &docs[idx + s.len()..]); | ||
134 | // Ensure to match the full word | ||
135 | if after.starts_with('!') | ||
136 | && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric()) | ||
137 | { | ||
138 | // It may have spaces before the braces like `foo! {}` | ||
139 | match after[1..].chars().find(|&c| !c.is_whitespace()) { | ||
140 | Some('{') => votes[0] += 1, | ||
141 | Some('[') => votes[1] += 1, | ||
142 | Some('(') => votes[2] += 1, | ||
143 | _ => {} | ||
144 | } | 129 | } |
145 | } | 130 | } |
146 | } | 131 | } |
147 | 132 | ||
148 | // Insert a space before `{}`. | 133 | completion_item.kind(kind).set_documentation(docs).add_to(self) |
149 | // We prefer the last one when some votes equal. | ||
150 | *votes.iter().zip(&[" {$0}", "[$0]", "($0)"]).max_by_key(|&(&vote, _)| vote).unwrap().1 | ||
151 | } | 134 | } |
152 | 135 | ||
153 | pub(crate) fn add_macro( | 136 | pub(crate) fn add_macro( |
@@ -156,6 +139,12 @@ impl Completions { | |||
156 | name: Option<String>, | 139 | name: Option<String>, |
157 | macro_: hir::MacroDef, | 140 | macro_: hir::MacroDef, |
158 | ) { | 141 | ) { |
142 | // FIXME: Currently proc-macro do not have ast-node, | ||
143 | // such that it does not have source | ||
144 | if macro_.is_proc_macro() { | ||
145 | return; | ||
146 | } | ||
147 | |||
159 | let name = match name { | 148 | let name = match name { |
160 | Some(it) => it, | 149 | Some(it) => it, |
161 | None => return, | 150 | None => return, |
@@ -165,22 +154,31 @@ impl Completions { | |||
165 | let detail = macro_label(&ast_node); | 154 | let detail = macro_label(&ast_node); |
166 | 155 | ||
167 | let docs = macro_.docs(ctx.db); | 156 | let docs = macro_.docs(ctx.db); |
168 | let macro_declaration = format!("{}!", name); | ||
169 | 157 | ||
170 | let mut builder = | 158 | let mut builder = CompletionItem::new( |
171 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), ¯o_declaration) | 159 | CompletionKind::Reference, |
172 | .kind(CompletionItemKind::Macro) | 160 | ctx.source_range(), |
173 | .set_documentation(docs.clone()) | 161 | &format!("{}!", name), |
174 | .set_deprecated(is_deprecated(macro_, ctx.db)) | 162 | ) |
175 | .detail(detail); | 163 | .kind(CompletionItemKind::Macro) |
164 | .set_documentation(docs.clone()) | ||
165 | .set_deprecated(is_deprecated(macro_, ctx.db)) | ||
166 | .detail(detail); | ||
176 | 167 | ||
177 | builder = if ctx.use_item_syntax.is_some() || ctx.is_macro_call { | 168 | let needs_bang = ctx.use_item_syntax.is_none() && !ctx.is_macro_call; |
178 | tested_by!(dont_insert_macro_call_parens_unncessary); | 169 | builder = match ctx.config.snippet_cap { |
179 | builder.insert_text(name) | 170 | Some(cap) if needs_bang => { |
180 | } else { | 171 | let docs = docs.as_ref().map_or("", |s| s.as_str()); |
181 | let macro_braces_to_insert = | 172 | let (bra, ket) = guess_macro_braces(&name, docs); |
182 | self.guess_macro_braces(&name, docs.as_ref().map_or("", |s| s.as_str())); | 173 | builder |
183 | builder.insert_snippet(macro_declaration + macro_braces_to_insert) | 174 | .insert_snippet(cap, format!("{}!{}$0{}", name, bra, ket)) |
175 | .label(format!("{}!{}…{}", name, bra, ket)) | ||
176 | } | ||
177 | None if needs_bang => builder.insert_text(format!("{}!", name)), | ||
178 | _ => { | ||
179 | tested_by!(dont_insert_macro_call_parens_unncessary); | ||
180 | builder.insert_text(name) | ||
181 | } | ||
184 | }; | 182 | }; |
185 | 183 | ||
186 | self.add(builder); | 184 | self.add(builder); |
@@ -294,6 +292,42 @@ impl Completions { | |||
294 | } | 292 | } |
295 | } | 293 | } |
296 | 294 | ||
295 | pub(crate) fn compute_score( | ||
296 | ctx: &CompletionContext, | ||
297 | // FIXME: this definitely should be a `Type` | ||
298 | ty: &str, | ||
299 | name: &str, | ||
300 | ) -> Option<CompletionScore> { | ||
301 | let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax { | ||
302 | tested_by!(test_struct_field_completion_in_record_lit); | ||
303 | let (struct_field, _local) = ctx.sema.resolve_record_field(record_field)?; | ||
304 | ( | ||
305 | struct_field.name(ctx.db).to_string(), | ||
306 | struct_field.signature_ty(ctx.db).display(ctx.db).to_string(), | ||
307 | ) | ||
308 | } else if let Some(active_parameter) = &ctx.active_parameter { | ||
309 | tested_by!(test_struct_field_completion_in_func_call); | ||
310 | (active_parameter.name.clone(), active_parameter.ty.clone()) | ||
311 | } else { | ||
312 | return None; | ||
313 | }; | ||
314 | |||
315 | // Compute score | ||
316 | // For the same type | ||
317 | if &active_type != ty { | ||
318 | return None; | ||
319 | } | ||
320 | |||
321 | let mut res = CompletionScore::TypeMatch; | ||
322 | |||
323 | // If same type + same name then go top position | ||
324 | if active_name == name { | ||
325 | res = CompletionScore::TypeAndNameMatch | ||
326 | } | ||
327 | |||
328 | Some(res) | ||
329 | } | ||
330 | |||
297 | enum Params { | 331 | enum Params { |
298 | Named(Vec<String>), | 332 | Named(Vec<String>), |
299 | Anonymous(usize), | 333 | Anonymous(usize), |
@@ -320,6 +354,10 @@ impl Builder { | |||
320 | if ctx.use_item_syntax.is_some() || ctx.is_call { | 354 | if ctx.use_item_syntax.is_some() || ctx.is_call { |
321 | return self; | 355 | return self; |
322 | } | 356 | } |
357 | let cap = match ctx.config.snippet_cap { | ||
358 | Some(it) => it, | ||
359 | None => return self, | ||
360 | }; | ||
323 | // If not an import, add parenthesis automatically. | 361 | // If not an import, add parenthesis automatically. |
324 | tested_by!(inserts_parens_for_function_calls); | 362 | tested_by!(inserts_parens_for_function_calls); |
325 | 363 | ||
@@ -341,7 +379,7 @@ impl Builder { | |||
341 | 379 | ||
342 | (snippet, format!("{}(…)", name)) | 380 | (snippet, format!("{}(…)", name)) |
343 | }; | 381 | }; |
344 | self.lookup_by(name).label(label).insert_snippet(snippet) | 382 | self.lookup_by(name).label(label).insert_snippet(cap, snippet) |
345 | } | 383 | } |
346 | } | 384 | } |
347 | 385 | ||
@@ -349,6 +387,34 @@ fn is_deprecated(node: impl HasAttrs, db: &RootDatabase) -> bool { | |||
349 | node.attrs(db).by_key("deprecated").exists() | 387 | node.attrs(db).by_key("deprecated").exists() |
350 | } | 388 | } |
351 | 389 | ||
390 | fn guess_macro_braces(macro_name: &str, docs: &str) -> (&'static str, &'static str) { | ||
391 | let mut votes = [0, 0, 0]; | ||
392 | for (idx, s) in docs.match_indices(¯o_name) { | ||
393 | let (before, after) = (&docs[..idx], &docs[idx + s.len()..]); | ||
394 | // Ensure to match the full word | ||
395 | if after.starts_with('!') | ||
396 | && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric()) | ||
397 | { | ||
398 | // It may have spaces before the braces like `foo! {}` | ||
399 | match after[1..].chars().find(|&c| !c.is_whitespace()) { | ||
400 | Some('{') => votes[0] += 1, | ||
401 | Some('[') => votes[1] += 1, | ||
402 | Some('(') => votes[2] += 1, | ||
403 | _ => {} | ||
404 | } | ||
405 | } | ||
406 | } | ||
407 | |||
408 | // Insert a space before `{}`. | ||
409 | // We prefer the last one when some votes equal. | ||
410 | let (_vote, (bra, ket)) = votes | ||
411 | .iter() | ||
412 | .zip(&[(" {", "}"), ("[", "]"), ("(", ")")]) | ||
413 | .max_by_key(|&(&vote, _)| vote) | ||
414 | .unwrap(); | ||
415 | (*bra, *ket) | ||
416 | } | ||
417 | |||
352 | #[cfg(test)] | 418 | #[cfg(test)] |
353 | mod tests { | 419 | mod tests { |
354 | use insta::assert_debug_snapshot; | 420 | use insta::assert_debug_snapshot; |
@@ -1025,4 +1091,237 @@ mod tests { | |||
1025 | "### | 1091 | "### |
1026 | ); | 1092 | ); |
1027 | } | 1093 | } |
1094 | |||
1095 | #[test] | ||
1096 | fn test_struct_field_completion_in_func_call() { | ||
1097 | covers!(test_struct_field_completion_in_func_call); | ||
1098 | assert_debug_snapshot!( | ||
1099 | do_reference_completion( | ||
1100 | r" | ||
1101 | struct A { another_field: i64, the_field: u32, my_string: String } | ||
1102 | fn test(my_param: u32) -> u32 { my_param } | ||
1103 | fn foo(a: A) { | ||
1104 | test(a.<|>) | ||
1105 | } | ||
1106 | ", | ||
1107 | ), | ||
1108 | @r###" | ||
1109 | [ | ||
1110 | CompletionItem { | ||
1111 | label: "another_field", | ||
1112 | source_range: [201; 201), | ||
1113 | delete: [201; 201), | ||
1114 | insert: "another_field", | ||
1115 | kind: Field, | ||
1116 | detail: "i64", | ||
1117 | }, | ||
1118 | CompletionItem { | ||
1119 | label: "my_string", | ||
1120 | source_range: [201; 201), | ||
1121 | delete: [201; 201), | ||
1122 | insert: "my_string", | ||
1123 | kind: Field, | ||
1124 | detail: "{unknown}", | ||
1125 | }, | ||
1126 | CompletionItem { | ||
1127 | label: "the_field", | ||
1128 | source_range: [201; 201), | ||
1129 | delete: [201; 201), | ||
1130 | insert: "the_field", | ||
1131 | kind: Field, | ||
1132 | detail: "u32", | ||
1133 | score: TypeMatch, | ||
1134 | }, | ||
1135 | ] | ||
1136 | "### | ||
1137 | ); | ||
1138 | } | ||
1139 | |||
1140 | #[test] | ||
1141 | fn test_struct_field_completion_in_func_call_with_type_and_name() { | ||
1142 | assert_debug_snapshot!( | ||
1143 | do_reference_completion( | ||
1144 | r" | ||
1145 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | ||
1146 | fn test(the_field: u32) -> u32 { the_field } | ||
1147 | fn foo(a: A) { | ||
1148 | test(a.<|>) | ||
1149 | } | ||
1150 | ", | ||
1151 | ), | ||
1152 | @r###" | ||
1153 | [ | ||
1154 | CompletionItem { | ||
1155 | label: "another_field", | ||
1156 | source_range: [208; 208), | ||
1157 | delete: [208; 208), | ||
1158 | insert: "another_field", | ||
1159 | kind: Field, | ||
1160 | detail: "i64", | ||
1161 | }, | ||
1162 | CompletionItem { | ||
1163 | label: "another_good_type", | ||
1164 | source_range: [208; 208), | ||
1165 | delete: [208; 208), | ||
1166 | insert: "another_good_type", | ||
1167 | kind: Field, | ||
1168 | detail: "u32", | ||
1169 | score: TypeMatch, | ||
1170 | }, | ||
1171 | CompletionItem { | ||
1172 | label: "the_field", | ||
1173 | source_range: [208; 208), | ||
1174 | delete: [208; 208), | ||
1175 | insert: "the_field", | ||
1176 | kind: Field, | ||
1177 | detail: "u32", | ||
1178 | score: TypeAndNameMatch, | ||
1179 | }, | ||
1180 | ] | ||
1181 | "### | ||
1182 | ); | ||
1183 | } | ||
1184 | |||
1185 | #[test] | ||
1186 | fn test_struct_field_completion_in_record_lit() { | ||
1187 | covers!(test_struct_field_completion_in_func_call); | ||
1188 | assert_debug_snapshot!( | ||
1189 | do_reference_completion( | ||
1190 | r" | ||
1191 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | ||
1192 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } | ||
1193 | fn foo(a: A) { | ||
1194 | let b = B { | ||
1195 | the_field: a.<|> | ||
1196 | }; | ||
1197 | } | ||
1198 | ", | ||
1199 | ), | ||
1200 | @r###" | ||
1201 | [ | ||
1202 | CompletionItem { | ||
1203 | label: "another_field", | ||
1204 | source_range: [270; 270), | ||
1205 | delete: [270; 270), | ||
1206 | insert: "another_field", | ||
1207 | kind: Field, | ||
1208 | detail: "i64", | ||
1209 | }, | ||
1210 | CompletionItem { | ||
1211 | label: "another_good_type", | ||
1212 | source_range: [270; 270), | ||
1213 | delete: [270; 270), | ||
1214 | insert: "another_good_type", | ||
1215 | kind: Field, | ||
1216 | detail: "u32", | ||
1217 | score: TypeMatch, | ||
1218 | }, | ||
1219 | CompletionItem { | ||
1220 | label: "the_field", | ||
1221 | source_range: [270; 270), | ||
1222 | delete: [270; 270), | ||
1223 | insert: "the_field", | ||
1224 | kind: Field, | ||
1225 | detail: "u32", | ||
1226 | score: TypeAndNameMatch, | ||
1227 | }, | ||
1228 | ] | ||
1229 | "### | ||
1230 | ); | ||
1231 | } | ||
1232 | |||
1233 | #[test] | ||
1234 | fn test_struct_field_completion_in_record_lit_and_fn_call() { | ||
1235 | assert_debug_snapshot!( | ||
1236 | do_reference_completion( | ||
1237 | r" | ||
1238 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | ||
1239 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } | ||
1240 | fn test(the_field: i64) -> i64 { the_field } | ||
1241 | fn foo(a: A) { | ||
1242 | let b = B { | ||
1243 | the_field: test(a.<|>) | ||
1244 | }; | ||
1245 | } | ||
1246 | ", | ||
1247 | ), | ||
1248 | @r###" | ||
1249 | [ | ||
1250 | CompletionItem { | ||
1251 | label: "another_field", | ||
1252 | source_range: [336; 336), | ||
1253 | delete: [336; 336), | ||
1254 | insert: "another_field", | ||
1255 | kind: Field, | ||
1256 | detail: "i64", | ||
1257 | score: TypeMatch, | ||
1258 | }, | ||
1259 | CompletionItem { | ||
1260 | label: "another_good_type", | ||
1261 | source_range: [336; 336), | ||
1262 | delete: [336; 336), | ||
1263 | insert: "another_good_type", | ||
1264 | kind: Field, | ||
1265 | detail: "u32", | ||
1266 | }, | ||
1267 | CompletionItem { | ||
1268 | label: "the_field", | ||
1269 | source_range: [336; 336), | ||
1270 | delete: [336; 336), | ||
1271 | insert: "the_field", | ||
1272 | kind: Field, | ||
1273 | detail: "u32", | ||
1274 | }, | ||
1275 | ] | ||
1276 | "### | ||
1277 | ); | ||
1278 | } | ||
1279 | |||
1280 | #[test] | ||
1281 | fn test_struct_field_completion_in_fn_call_and_record_lit() { | ||
1282 | assert_debug_snapshot!( | ||
1283 | do_reference_completion( | ||
1284 | r" | ||
1285 | struct A { another_field: i64, another_good_type: u32, the_field: u32 } | ||
1286 | struct B { my_string: String, my_vec: Vec<u32>, the_field: u32 } | ||
1287 | fn test(the_field: i64) -> i64 { the_field } | ||
1288 | fn foo(a: A) { | ||
1289 | test(B { | ||
1290 | the_field: a.<|> | ||
1291 | }); | ||
1292 | } | ||
1293 | ", | ||
1294 | ), | ||
1295 | @r###" | ||
1296 | [ | ||
1297 | CompletionItem { | ||
1298 | label: "another_field", | ||
1299 | source_range: [328; 328), | ||
1300 | delete: [328; 328), | ||
1301 | insert: "another_field", | ||
1302 | kind: Field, | ||
1303 | detail: "i64", | ||
1304 | }, | ||
1305 | CompletionItem { | ||
1306 | label: "another_good_type", | ||
1307 | source_range: [328; 328), | ||
1308 | delete: [328; 328), | ||
1309 | insert: "another_good_type", | ||
1310 | kind: Field, | ||
1311 | detail: "u32", | ||
1312 | score: TypeMatch, | ||
1313 | }, | ||
1314 | CompletionItem { | ||
1315 | label: "the_field", | ||
1316 | source_range: [328; 328), | ||
1317 | delete: [328; 328), | ||
1318 | insert: "the_field", | ||
1319 | kind: Field, | ||
1320 | detail: "u32", | ||
1321 | score: TypeAndNameMatch, | ||
1322 | }, | ||
1323 | ] | ||
1324 | "### | ||
1325 | ); | ||
1326 | } | ||
1028 | } | 1327 | } |
diff --git a/crates/ra_ide/src/display/function_signature.rs b/crates/ra_ide/src/display/function_signature.rs index b967a6816..b5e2785fe 100644 --- a/crates/ra_ide/src/display/function_signature.rs +++ b/crates/ra_ide/src/display/function_signature.rs | |||
@@ -36,6 +36,8 @@ pub struct FunctionSignature { | |||
36 | pub parameters: Vec<String>, | 36 | pub parameters: Vec<String>, |
37 | /// Parameter names of the function | 37 | /// Parameter names of the function |
38 | pub parameter_names: Vec<String>, | 38 | pub parameter_names: Vec<String>, |
39 | /// Parameter types of the function | ||
40 | pub parameter_types: Vec<String>, | ||
39 | /// Optional return type | 41 | /// Optional return type |
40 | pub ret_type: Option<String>, | 42 | pub ret_type: Option<String>, |
41 | /// Where predicates | 43 | /// Where predicates |
@@ -62,14 +64,20 @@ impl FunctionSignature { | |||
62 | return None; | 64 | return None; |
63 | }; | 65 | }; |
64 | 66 | ||
65 | let params = st | 67 | let mut params = vec![]; |
66 | .fields(db) | 68 | let mut parameter_types = vec![]; |
67 | .into_iter() | 69 | for field in st.fields(db).into_iter() { |
68 | .map(|field: hir::StructField| { | 70 | let ty = field.signature_ty(db); |
69 | let ty = field.signature_ty(db); | 71 | let raw_param = format!("{}", ty.display(db)); |
70 | format!("{}", ty.display(db)) | 72 | |
71 | }) | 73 | if let Some(param_type) = raw_param.split(':').nth(1) { |
72 | .collect(); | 74 | parameter_types.push(param_type[1..].to_string()); |
75 | } else { | ||
76 | // useful when you have tuple struct | ||
77 | parameter_types.push(raw_param.clone()); | ||
78 | } | ||
79 | params.push(raw_param); | ||
80 | } | ||
73 | 81 | ||
74 | Some( | 82 | Some( |
75 | FunctionSignature { | 83 | FunctionSignature { |
@@ -79,6 +87,7 @@ impl FunctionSignature { | |||
79 | ret_type: node.name().map(|n| n.text().to_string()), | 87 | ret_type: node.name().map(|n| n.text().to_string()), |
80 | parameters: params, | 88 | parameters: params, |
81 | parameter_names: vec![], | 89 | parameter_names: vec![], |
90 | parameter_types, | ||
82 | generic_parameters: generic_parameters(&node), | 91 | generic_parameters: generic_parameters(&node), |
83 | where_predicates: where_predicates(&node), | 92 | where_predicates: where_predicates(&node), |
84 | doc: None, | 93 | doc: None, |
@@ -99,15 +108,21 @@ impl FunctionSignature { | |||
99 | 108 | ||
100 | let name = format!("{}::{}", parent_name, variant.name(db)); | 109 | let name = format!("{}::{}", parent_name, variant.name(db)); |
101 | 110 | ||
102 | let params = variant | 111 | let mut params = vec![]; |
103 | .fields(db) | 112 | let mut parameter_types = vec![]; |
104 | .into_iter() | 113 | for field in variant.fields(db).into_iter() { |
105 | .map(|field: hir::StructField| { | 114 | let ty = field.signature_ty(db); |
106 | let name = field.name(db); | 115 | let raw_param = format!("{}", ty.display(db)); |
107 | let ty = field.signature_ty(db); | 116 | if let Some(param_type) = raw_param.split(':').nth(1) { |
108 | format!("{}: {}", name, ty.display(db)) | 117 | parameter_types.push(param_type[1..].to_string()); |
109 | }) | 118 | } else { |
110 | .collect(); | 119 | // The unwrap_or_else is useful when you have tuple |
120 | parameter_types.push(raw_param); | ||
121 | } | ||
122 | let name = field.name(db); | ||
123 | |||
124 | params.push(format!("{}: {}", name, ty.display(db))); | ||
125 | } | ||
111 | 126 | ||
112 | Some( | 127 | Some( |
113 | FunctionSignature { | 128 | FunctionSignature { |
@@ -117,6 +132,7 @@ impl FunctionSignature { | |||
117 | ret_type: None, | 132 | ret_type: None, |
118 | parameters: params, | 133 | parameters: params, |
119 | parameter_names: vec![], | 134 | parameter_names: vec![], |
135 | parameter_types, | ||
120 | generic_parameters: vec![], | 136 | generic_parameters: vec![], |
121 | where_predicates: vec![], | 137 | where_predicates: vec![], |
122 | doc: None, | 138 | doc: None, |
@@ -139,6 +155,7 @@ impl FunctionSignature { | |||
139 | ret_type: None, | 155 | ret_type: None, |
140 | parameters: params, | 156 | parameters: params, |
141 | parameter_names: vec![], | 157 | parameter_names: vec![], |
158 | parameter_types: vec![], | ||
142 | generic_parameters: vec![], | 159 | generic_parameters: vec![], |
143 | where_predicates: vec![], | 160 | where_predicates: vec![], |
144 | doc: None, | 161 | doc: None, |
@@ -151,18 +168,27 @@ impl FunctionSignature { | |||
151 | 168 | ||
152 | impl From<&'_ ast::FnDef> for FunctionSignature { | 169 | impl From<&'_ ast::FnDef> for FunctionSignature { |
153 | fn from(node: &ast::FnDef) -> FunctionSignature { | 170 | fn from(node: &ast::FnDef) -> FunctionSignature { |
154 | fn param_list(node: &ast::FnDef) -> (bool, Vec<String>) { | 171 | fn param_list(node: &ast::FnDef) -> (bool, Vec<String>, Vec<String>) { |
155 | let mut res = vec![]; | 172 | let mut res = vec![]; |
173 | let mut res_types = vec![]; | ||
156 | let mut has_self_param = false; | 174 | let mut has_self_param = false; |
157 | if let Some(param_list) = node.param_list() { | 175 | if let Some(param_list) = node.param_list() { |
158 | if let Some(self_param) = param_list.self_param() { | 176 | if let Some(self_param) = param_list.self_param() { |
159 | has_self_param = true; | 177 | has_self_param = true; |
160 | res.push(self_param.syntax().text().to_string()) | 178 | let raw_param = self_param.syntax().text().to_string(); |
179 | |||
180 | res_types.push( | ||
181 | raw_param.split(':').nth(1).unwrap_or_else(|| " Self")[1..].to_string(), | ||
182 | ); | ||
183 | res.push(raw_param); | ||
161 | } | 184 | } |
162 | 185 | ||
163 | res.extend(param_list.params().map(|param| param.syntax().text().to_string())); | 186 | res.extend(param_list.params().map(|param| param.syntax().text().to_string())); |
187 | res_types.extend(param_list.params().map(|param| { | ||
188 | param.syntax().text().to_string().split(':').nth(1).unwrap()[1..].to_string() | ||
189 | })); | ||
164 | } | 190 | } |
165 | (has_self_param, res) | 191 | (has_self_param, res, res_types) |
166 | } | 192 | } |
167 | 193 | ||
168 | fn param_name_list(node: &ast::FnDef) -> Vec<String> { | 194 | fn param_name_list(node: &ast::FnDef) -> Vec<String> { |
@@ -192,7 +218,7 @@ impl From<&'_ ast::FnDef> for FunctionSignature { | |||
192 | res | 218 | res |
193 | } | 219 | } |
194 | 220 | ||
195 | let (has_self_param, parameters) = param_list(node); | 221 | let (has_self_param, parameters, parameter_types) = param_list(node); |
196 | 222 | ||
197 | FunctionSignature { | 223 | FunctionSignature { |
198 | kind: CallableKind::Function, | 224 | kind: CallableKind::Function, |
@@ -204,6 +230,7 @@ impl From<&'_ ast::FnDef> for FunctionSignature { | |||
204 | .map(|n| n.syntax().text().to_string()), | 230 | .map(|n| n.syntax().text().to_string()), |
205 | parameters, | 231 | parameters, |
206 | parameter_names: param_name_list(node), | 232 | parameter_names: param_name_list(node), |
233 | parameter_types, | ||
207 | generic_parameters: generic_parameters(node), | 234 | generic_parameters: generic_parameters(node), |
208 | where_predicates: where_predicates(node), | 235 | where_predicates: where_predicates(node), |
209 | // docs are processed separately | 236 | // docs are processed separately |
diff --git a/crates/ra_ide/src/display/navigation_target.rs b/crates/ra_ide/src/display/navigation_target.rs index 6289f53f3..67bc9c31b 100644 --- a/crates/ra_ide/src/display/navigation_target.rs +++ b/crates/ra_ide/src/display/navigation_target.rs | |||
@@ -176,7 +176,7 @@ impl ToNav for FileSymbol { | |||
176 | file_id: self.file_id, | 176 | file_id: self.file_id, |
177 | name: self.name.clone(), | 177 | name: self.name.clone(), |
178 | kind: self.kind, | 178 | kind: self.kind, |
179 | full_range: self.ptr.range(), | 179 | full_range: self.range, |
180 | focus_range: self.name_range, | 180 | focus_range: self.name_range, |
181 | container_name: self.container_name.clone(), | 181 | container_name: self.container_name.clone(), |
182 | description: description_from_symbol(db, self), | 182 | description: description_from_symbol(db, self), |
diff --git a/crates/ra_ide/src/extend_selection.rs b/crates/ra_ide/src/extend_selection.rs index f5a063351..753d2ef6a 100644 --- a/crates/ra_ide/src/extend_selection.rs +++ b/crates/ra_ide/src/extend_selection.rs | |||
@@ -96,7 +96,7 @@ fn try_extend_selection( | |||
96 | return Some(node.text_range()); | 96 | return Some(node.text_range()); |
97 | } | 97 | } |
98 | 98 | ||
99 | let node = shallowest_node(&node.into()); | 99 | let node = shallowest_node(&node); |
100 | 100 | ||
101 | if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) { | 101 | if node.parent().map(|n| list_kinds.contains(&n.kind())) == Some(true) { |
102 | if let Some(range) = extend_list_item(&node) { | 102 | if let Some(range) = extend_list_item(&node) { |
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs index 8aed94d16..9998ca5a3 100644 --- a/crates/ra_ide/src/goto_definition.rs +++ b/crates/ra_ide/src/goto_definition.rs | |||
@@ -62,10 +62,9 @@ pub(crate) enum ReferenceResult { | |||
62 | 62 | ||
63 | impl ReferenceResult { | 63 | impl ReferenceResult { |
64 | fn to_vec(self) -> Vec<NavigationTarget> { | 64 | fn to_vec(self) -> Vec<NavigationTarget> { |
65 | use self::ReferenceResult::*; | ||
66 | match self { | 65 | match self { |
67 | Exact(target) => vec![target], | 66 | ReferenceResult::Exact(target) => vec![target], |
68 | Approximate(vec) => vec, | 67 | ReferenceResult::Approximate(vec) => vec, |
69 | } | 68 | } |
70 | } | 69 | } |
71 | } | 70 | } |
@@ -74,8 +73,6 @@ pub(crate) fn reference_definition( | |||
74 | sema: &Semantics<RootDatabase>, | 73 | sema: &Semantics<RootDatabase>, |
75 | name_ref: &ast::NameRef, | 74 | name_ref: &ast::NameRef, |
76 | ) -> ReferenceResult { | 75 | ) -> ReferenceResult { |
77 | use self::ReferenceResult::*; | ||
78 | |||
79 | let name_kind = classify_name_ref(sema, name_ref); | 76 | let name_kind = classify_name_ref(sema, name_ref); |
80 | if let Some(def) = name_kind { | 77 | if let Some(def) = name_kind { |
81 | let def = def.definition(); | 78 | let def = def.definition(); |
@@ -91,7 +88,7 @@ pub(crate) fn reference_definition( | |||
91 | .into_iter() | 88 | .into_iter() |
92 | .map(|s| s.to_nav(sema.db)) | 89 | .map(|s| s.to_nav(sema.db)) |
93 | .collect(); | 90 | .collect(); |
94 | Approximate(navs) | 91 | ReferenceResult::Approximate(navs) |
95 | } | 92 | } |
96 | 93 | ||
97 | #[cfg(test)] | 94 | #[cfg(test)] |
@@ -399,6 +396,25 @@ mod tests { | |||
399 | } | 396 | } |
400 | 397 | ||
401 | #[test] | 398 | #[test] |
399 | fn goto_def_for_record_pat_fields() { | ||
400 | covers!(ra_ide_db::goto_def_for_record_field_pats); | ||
401 | check_goto( | ||
402 | r" | ||
403 | //- /lib.rs | ||
404 | struct Foo { | ||
405 | spam: u32, | ||
406 | } | ||
407 | |||
408 | fn bar(foo: Foo) -> Foo { | ||
409 | let Foo { spam<|>: _, } = foo | ||
410 | } | ||
411 | ", | ||
412 | "spam RECORD_FIELD_DEF FileId(1) [17; 26) [17; 21)", | ||
413 | "spam: u32|spam", | ||
414 | ); | ||
415 | } | ||
416 | |||
417 | #[test] | ||
402 | fn goto_def_for_record_fields_macros() { | 418 | fn goto_def_for_record_fields_macros() { |
403 | check_goto( | 419 | check_goto( |
404 | r" | 420 | r" |
diff --git a/crates/ra_ide/src/lib.rs b/crates/ra_ide/src/lib.rs index 5599f143f..f692fbaa2 100644 --- a/crates/ra_ide/src/lib.rs +++ b/crates/ra_ide/src/lib.rs | |||
@@ -67,7 +67,9 @@ use crate::display::ToNav; | |||
67 | pub use crate::{ | 67 | pub use crate::{ |
68 | assists::{Assist, AssistId}, | 68 | assists::{Assist, AssistId}, |
69 | call_hierarchy::CallItem, | 69 | call_hierarchy::CallItem, |
70 | completion::{CompletionConfig, CompletionItem, CompletionItemKind, InsertTextFormat}, | 70 | completion::{ |
71 | CompletionConfig, CompletionItem, CompletionItemKind, CompletionScore, InsertTextFormat, | ||
72 | }, | ||
71 | diagnostics::Severity, | 73 | diagnostics::Severity, |
72 | display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, | 74 | display::{file_structure, FunctionSignature, NavigationTarget, StructureNode}, |
73 | expand_macro::ExpandedMacro, | 75 | expand_macro::ExpandedMacro, |
diff --git a/crates/ra_ide/src/marks.rs b/crates/ra_ide/src/marks.rs index eee44e886..bea30fe2a 100644 --- a/crates/ra_ide/src/marks.rs +++ b/crates/ra_ide/src/marks.rs | |||
@@ -9,4 +9,6 @@ test_utils::marks!( | |||
9 | search_filters_by_range | 9 | search_filters_by_range |
10 | dont_insert_macro_call_parens_unncessary | 10 | dont_insert_macro_call_parens_unncessary |
11 | self_fulfilling_completion | 11 | self_fulfilling_completion |
12 | test_struct_field_completion_in_func_call | ||
13 | test_struct_field_completion_in_record_lit | ||
12 | ); | 14 | ); |
diff --git a/crates/ra_ide/src/runnables.rs b/crates/ra_ide/src/runnables.rs index 9433f3a24..05a66e03c 100644 --- a/crates/ra_ide/src/runnables.rs +++ b/crates/ra_ide/src/runnables.rs | |||
@@ -34,7 +34,7 @@ impl Display for TestId { | |||
34 | 34 | ||
35 | #[derive(Debug)] | 35 | #[derive(Debug)] |
36 | pub enum RunnableKind { | 36 | pub enum RunnableKind { |
37 | Test { test_id: TestId }, | 37 | Test { test_id: TestId, attr: TestAttr }, |
38 | TestMod { path: String }, | 38 | TestMod { path: String }, |
39 | Bench { test_id: TestId }, | 39 | Bench { test_id: TestId }, |
40 | Bin, | 40 | Bin, |
@@ -77,7 +77,8 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run | |||
77 | }; | 77 | }; |
78 | 78 | ||
79 | if has_test_related_attribute(&fn_def) { | 79 | if has_test_related_attribute(&fn_def) { |
80 | RunnableKind::Test { test_id } | 80 | let attr = TestAttr::from_fn(&fn_def); |
81 | RunnableKind::Test { test_id, attr } | ||
81 | } else if fn_def.has_atom_attr("bench") { | 82 | } else if fn_def.has_atom_attr("bench") { |
82 | RunnableKind::Bench { test_id } | 83 | RunnableKind::Bench { test_id } |
83 | } else { | 84 | } else { |
@@ -87,6 +88,21 @@ fn runnable_fn(sema: &Semantics<RootDatabase>, fn_def: ast::FnDef) -> Option<Run | |||
87 | Some(Runnable { range: fn_def.syntax().text_range(), kind }) | 88 | Some(Runnable { range: fn_def.syntax().text_range(), kind }) |
88 | } | 89 | } |
89 | 90 | ||
91 | #[derive(Debug)] | ||
92 | pub struct TestAttr { | ||
93 | pub ignore: bool, | ||
94 | } | ||
95 | |||
96 | impl TestAttr { | ||
97 | fn from_fn(fn_def: &ast::FnDef) -> TestAttr { | ||
98 | let ignore = fn_def | ||
99 | .attrs() | ||
100 | .filter_map(|attr| attr.simple_name()) | ||
101 | .any(|attribute_text| attribute_text == "ignore"); | ||
102 | TestAttr { ignore } | ||
103 | } | ||
104 | } | ||
105 | |||
90 | /// This is a method with a heuristics to support test methods annotated with custom test annotations, such as | 106 | /// This is a method with a heuristics to support test methods annotated with custom test annotations, such as |
91 | /// `#[test_case(...)]`, `#[tokio::test]` and similar. | 107 | /// `#[test_case(...)]`, `#[tokio::test]` and similar. |
92 | /// Also a regular `#[test]` annotation is supported. | 108 | /// Also a regular `#[test]` annotation is supported. |
@@ -157,6 +173,9 @@ mod tests { | |||
157 | test_id: Path( | 173 | test_id: Path( |
158 | "test_foo", | 174 | "test_foo", |
159 | ), | 175 | ), |
176 | attr: TestAttr { | ||
177 | ignore: false, | ||
178 | }, | ||
160 | }, | 179 | }, |
161 | }, | 180 | }, |
162 | Runnable { | 181 | Runnable { |
@@ -165,6 +184,9 @@ mod tests { | |||
165 | test_id: Path( | 184 | test_id: Path( |
166 | "test_foo", | 185 | "test_foo", |
167 | ), | 186 | ), |
187 | attr: TestAttr { | ||
188 | ignore: true, | ||
189 | }, | ||
168 | }, | 190 | }, |
169 | }, | 191 | }, |
170 | ] | 192 | ] |
@@ -200,6 +222,9 @@ mod tests { | |||
200 | test_id: Path( | 222 | test_id: Path( |
201 | "test_mod::test_foo1", | 223 | "test_mod::test_foo1", |
202 | ), | 224 | ), |
225 | attr: TestAttr { | ||
226 | ignore: false, | ||
227 | }, | ||
203 | }, | 228 | }, |
204 | }, | 229 | }, |
205 | ] | 230 | ] |
@@ -237,6 +262,9 @@ mod tests { | |||
237 | test_id: Path( | 262 | test_id: Path( |
238 | "foo::test_mod::test_foo1", | 263 | "foo::test_mod::test_foo1", |
239 | ), | 264 | ), |
265 | attr: TestAttr { | ||
266 | ignore: false, | ||
267 | }, | ||
240 | }, | 268 | }, |
241 | }, | 269 | }, |
242 | ] | 270 | ] |
@@ -276,6 +304,9 @@ mod tests { | |||
276 | test_id: Path( | 304 | test_id: Path( |
277 | "foo::bar::test_mod::test_foo1", | 305 | "foo::bar::test_mod::test_foo1", |
278 | ), | 306 | ), |
307 | attr: TestAttr { | ||
308 | ignore: false, | ||
309 | }, | ||
279 | }, | 310 | }, |
280 | }, | 311 | }, |
281 | ] | 312 | ] |
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html index 214dcbb62..ccb1fc751 100644 --- a/crates/ra_ide/src/snapshots/highlighting.html +++ b/crates/ra_ide/src/snapshots/highlighting.html | |||
@@ -50,12 +50,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
50 | <span class="keyword">fn</span> <span class="function declaration">main</span>() { | 50 | <span class="keyword">fn</span> <span class="function declaration">main</span>() { |
51 | <span class="macro">println!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>); | 51 | <span class="macro">println!</span>(<span class="string_literal">"Hello, {}!"</span>, <span class="numeric_literal">92</span>); |
52 | 52 | ||
53 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">vec</span> = Vec::new(); | 53 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">vec</span> = <span class="unresolved_reference">Vec</span>::<span class="unresolved_reference">new</span>(); |
54 | <span class="keyword control">if</span> <span class="keyword">true</span> { | 54 | <span class="keyword control">if</span> <span class="keyword">true</span> { |
55 | <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>; | 55 | <span class="keyword">let</span> <span class="variable declaration">x</span> = <span class="numeric_literal">92</span>; |
56 | <span class="variable mutable">vec</span>.push(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> }); | 56 | <span class="variable mutable">vec</span>.<span class="unresolved_reference">push</span>(<span class="struct">Foo</span> { <span class="field">x</span>, <span class="field">y</span>: <span class="numeric_literal">1</span> }); |
57 | } | 57 | } |
58 | <span class="keyword unsafe">unsafe</span> { <span class="variable mutable">vec</span>.set_len(<span class="numeric_literal">0</span>); } | 58 | <span class="keyword unsafe">unsafe</span> { <span class="variable mutable">vec</span>.<span class="unresolved_reference">set_len</span>(<span class="numeric_literal">0</span>); } |
59 | 59 | ||
60 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; | 60 | <span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">x</span> = <span class="numeric_literal">42</span>; |
61 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; | 61 | <span class="keyword">let</span> <span class="variable declaration mutable">y</span> = &<span class="keyword">mut</span> <span class="variable mutable">x</span>; |
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html index dddbfc0dd..3df82c45f 100644 --- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html +++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html | |||
@@ -28,11 +28,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
28 | </style> | 28 | </style> |
29 | <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span>() { | 29 | <pre><code><span class="keyword">fn</span> <span class="function declaration">main</span>() { |
30 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>; | 30 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span> = <span class="string_literal">"hello"</span>; |
31 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(17,51%,74%);">x</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.to_string(); | 31 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="2705725358298919760" style="color: hsl(17,51%,74%);">x</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.<span class="unresolved_reference">to_string</span>(); |
32 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(127,76%,66%);">y</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.to_string(); | 32 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="3365759661443752373" style="color: hsl(127,76%,66%);">y</span> = <span class="variable" data-binding-hash="8121853618659664005" style="color: hsl(261,57%,61%);">hello</span>.<span class="unresolved_reference">to_string</span>(); |
33 | 33 | ||
34 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span> = <span class="string_literal">"other color please!"</span>; | 34 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span> = <span class="string_literal">"other color please!"</span>; |
35 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(85,49%,84%);">y</span> = <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span>.to_string(); | 35 | <span class="keyword">let</span> <span class="variable declaration" data-binding-hash="6717528807933952652" style="color: hsl(85,49%,84%);">y</span> = <span class="variable" data-binding-hash="794745962933817518" style="color: hsl(19,74%,76%);">x</span>.<span class="unresolved_reference">to_string</span>(); |
36 | } | 36 | } |
37 | 37 | ||
38 | <span class="keyword">fn</span> <span class="function declaration">bar</span>() { | 38 | <span class="keyword">fn</span> <span class="function declaration">bar</span>() { |
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs index b5fd3390f..c0728bfb1 100644 --- a/crates/ra_ide/src/syntax_highlighting.rs +++ b/crates/ra_ide/src/syntax_highlighting.rs | |||
@@ -19,7 +19,7 @@ use ra_syntax::{ | |||
19 | }; | 19 | }; |
20 | use rustc_hash::FxHashMap; | 20 | use rustc_hash::FxHashMap; |
21 | 21 | ||
22 | use crate::{call_info::call_info_for_token, Analysis, FileId}; | 22 | use crate::{call_info::ActiveParameter, Analysis, FileId}; |
23 | 23 | ||
24 | use ast::FormatSpecifier; | 24 | use ast::FormatSpecifier; |
25 | pub(crate) use html::highlight_as_html; | 25 | pub(crate) use html::highlight_as_html; |
@@ -351,20 +351,21 @@ fn highlight_element( | |||
351 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => return None, | 351 | NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => return None, |
352 | NAME_REF => { | 352 | NAME_REF => { |
353 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); | 353 | let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap(); |
354 | let name_kind = classify_name_ref(sema, &name_ref)?; | 354 | match classify_name_ref(sema, &name_ref) { |
355 | 355 | Some(name_kind) => match name_kind { | |
356 | match name_kind { | 356 | NameRefClass::Definition(def) => { |
357 | NameRefClass::Definition(def) => { | 357 | if let Definition::Local(local) = &def { |
358 | if let Definition::Local(local) = &def { | 358 | if let Some(name) = local.name(db) { |
359 | if let Some(name) = local.name(db) { | 359 | let shadow_count = |
360 | let shadow_count = | 360 | bindings_shadow_count.entry(name.clone()).or_default(); |
361 | bindings_shadow_count.entry(name.clone()).or_default(); | 361 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) |
362 | binding_hash = Some(calc_binding_hash(&name, *shadow_count)) | 362 | } |
363 | } | 363 | }; |
364 | }; | 364 | highlight_name(db, def) |
365 | highlight_name(db, def) | 365 | } |
366 | } | 366 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), |
367 | NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(), | 367 | }, |
368 | None => HighlightTag::UnresolvedReference.into(), | ||
368 | } | 369 | } |
369 | } | 370 | } |
370 | 371 | ||
@@ -475,10 +476,8 @@ fn highlight_injection( | |||
475 | literal: ast::RawString, | 476 | literal: ast::RawString, |
476 | expanded: SyntaxToken, | 477 | expanded: SyntaxToken, |
477 | ) -> Option<()> { | 478 | ) -> Option<()> { |
478 | let call_info = call_info_for_token(&sema, expanded)?; | 479 | let active_parameter = ActiveParameter::at_token(&sema, expanded)?; |
479 | let idx = call_info.active_parameter?; | 480 | if !active_parameter.name.starts_with("ra_fixture") { |
480 | let name = call_info.signature.parameter_names.get(idx)?; | ||
481 | if !name.starts_with("ra_fixture") { | ||
482 | return None; | 481 | return None; |
483 | } | 482 | } |
484 | let value = literal.value()?; | 483 | let value = literal.value()?; |
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs index e8b138e1a..f2c421654 100644 --- a/crates/ra_ide/src/syntax_highlighting/tags.rs +++ b/crates/ra_ide/src/syntax_highlighting/tags.rs | |||
@@ -38,6 +38,7 @@ pub enum HighlightTag { | |||
38 | TypeParam, | 38 | TypeParam, |
39 | Union, | 39 | Union, |
40 | Local, | 40 | Local, |
41 | UnresolvedReference, | ||
41 | } | 42 | } |
42 | 43 | ||
43 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | 44 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] |
@@ -79,6 +80,7 @@ impl HighlightTag { | |||
79 | HighlightTag::TypeParam => "type_param", | 80 | HighlightTag::TypeParam => "type_param", |
80 | HighlightTag::Union => "union", | 81 | HighlightTag::Union => "union", |
81 | HighlightTag::Local => "variable", | 82 | HighlightTag::Local => "variable", |
83 | HighlightTag::UnresolvedReference => "unresolved_reference", | ||
82 | } | 84 | } |
83 | } | 85 | } |
84 | } | 86 | } |
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs index 49a8c74fb..785613b82 100644 --- a/crates/ra_ide_db/src/defs.rs +++ b/crates/ra_ide_db/src/defs.rs | |||
@@ -180,6 +180,7 @@ fn classify_name_inner(sema: &Semantics<RootDatabase>, name: &ast::Name) -> Opti | |||
180 | } | 180 | } |
181 | } | 181 | } |
182 | 182 | ||
183 | #[derive(Debug)] | ||
183 | pub enum NameRefClass { | 184 | pub enum NameRefClass { |
184 | Definition(Definition), | 185 | Definition(Definition), |
185 | FieldShorthand { local: Local, field: Definition }, | 186 | FieldShorthand { local: Local, field: Definition }, |
@@ -229,6 +230,14 @@ pub fn classify_name_ref( | |||
229 | } | 230 | } |
230 | } | 231 | } |
231 | 232 | ||
233 | if let Some(record_field_pat) = ast::RecordFieldPat::cast(parent.clone()) { | ||
234 | tested_by!(goto_def_for_record_field_pats; force); | ||
235 | if let Some(field) = sema.resolve_record_field_pat(&record_field_pat) { | ||
236 | let field = Definition::StructField(field); | ||
237 | return Some(NameRefClass::Definition(field)); | ||
238 | } | ||
239 | } | ||
240 | |||
232 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { | 241 | if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { |
233 | tested_by!(goto_def_for_macros; force); | 242 | tested_by!(goto_def_for_macros; force); |
234 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { | 243 | if let Some(macro_def) = sema.resolve_macro_call(¯o_call) { |
diff --git a/crates/ra_ide_db/src/marks.rs b/crates/ra_ide_db/src/marks.rs index 4f0a22af0..03b4be21c 100644 --- a/crates/ra_ide_db/src/marks.rs +++ b/crates/ra_ide_db/src/marks.rs | |||
@@ -6,5 +6,6 @@ test_utils::marks![ | |||
6 | goto_def_for_fields | 6 | goto_def_for_fields |
7 | goto_def_for_record_fields | 7 | goto_def_for_record_fields |
8 | goto_def_for_field_init_shorthand | 8 | goto_def_for_field_init_shorthand |
9 | goto_def_for_record_field_pats | ||
9 | search_filters_by_range | 10 | search_filters_by_range |
10 | ]; | 11 | ]; |
diff --git a/crates/ra_ide_db/src/symbol_index.rs b/crates/ra_ide_db/src/symbol_index.rs index 937abb433..95be11134 100644 --- a/crates/ra_ide_db/src/symbol_index.rs +++ b/crates/ra_ide_db/src/symbol_index.rs | |||
@@ -313,6 +313,7 @@ pub struct FileSymbol { | |||
313 | pub file_id: FileId, | 313 | pub file_id: FileId, |
314 | pub name: SmolStr, | 314 | pub name: SmolStr, |
315 | pub kind: SyntaxKind, | 315 | pub kind: SyntaxKind, |
316 | pub range: TextRange, | ||
316 | pub ptr: SyntaxNodePtr, | 317 | pub ptr: SyntaxNodePtr, |
317 | pub name_range: Option<TextRange>, | 318 | pub name_range: Option<TextRange>, |
318 | pub container_name: Option<SmolStr>, | 319 | pub container_name: Option<SmolStr>, |
@@ -379,6 +380,7 @@ fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> { | |||
379 | to_symbol(node).map(move |(name, ptr, name_range)| FileSymbol { | 380 | to_symbol(node).map(move |(name, ptr, name_range)| FileSymbol { |
380 | name, | 381 | name, |
381 | kind: node.kind(), | 382 | kind: node.kind(), |
383 | range: node.text_range(), | ||
382 | ptr, | 384 | ptr, |
383 | file_id, | 385 | file_id, |
384 | name_range: Some(name_range), | 386 | name_range: Some(name_range), |
diff --git a/crates/ra_mbe/src/mbe_expander/matcher.rs b/crates/ra_mbe/src/mbe_expander/matcher.rs index 2579382da..78f9efa1b 100644 --- a/crates/ra_mbe/src/mbe_expander/matcher.rs +++ b/crates/ra_mbe/src/mbe_expander/matcher.rs | |||
@@ -187,7 +187,11 @@ impl<'a> TtIter<'a> { | |||
187 | _ => false, | 187 | _ => false, |
188 | }, | 188 | }, |
189 | Separator::Literal(lhs) => match fork.expect_literal() { | 189 | Separator::Literal(lhs) => match fork.expect_literal() { |
190 | Ok(rhs) => rhs.text == lhs.text, | 190 | Ok(rhs) => match rhs { |
191 | tt::Leaf::Literal(rhs) => rhs.text == lhs.text, | ||
192 | tt::Leaf::Ident(rhs) => rhs.text == lhs.text, | ||
193 | tt::Leaf::Punct(_) => false, | ||
194 | }, | ||
191 | _ => false, | 195 | _ => false, |
192 | }, | 196 | }, |
193 | Separator::Puncts(lhss) => lhss.iter().all(|lhs| match fork.expect_punct() { | 197 | Separator::Puncts(lhss) => lhss.iter().all(|lhs| match fork.expect_punct() { |
@@ -202,6 +206,13 @@ impl<'a> TtIter<'a> { | |||
202 | } | 206 | } |
203 | 207 | ||
204 | pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> { | 208 | pub(crate) fn expect_tt(&mut self) -> Result<tt::TokenTree, ()> { |
209 | match self.peek_n(0) { | ||
210 | Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) if punct.char == '\'' => { | ||
211 | return self.expect_lifetime(); | ||
212 | } | ||
213 | _ => (), | ||
214 | } | ||
215 | |||
205 | let tt = self.next().ok_or_else(|| ())?.clone(); | 216 | let tt = self.next().ok_or_else(|| ())?.clone(); |
206 | let punct = match tt { | 217 | let punct = match tt { |
207 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => { | 218 | tt::TokenTree::Leaf(tt::Leaf::Punct(punct)) if punct.spacing == tt::Spacing::Joint => { |
@@ -255,13 +266,21 @@ impl<'a> TtIter<'a> { | |||
255 | } | 266 | } |
256 | } | 267 | } |
257 | 268 | ||
258 | pub(crate) fn expect_lifetime(&mut self) -> Result<&tt::Ident, ()> { | 269 | pub(crate) fn expect_lifetime(&mut self) -> Result<tt::TokenTree, ()> { |
259 | let ident = self.expect_ident()?; | 270 | let punct = self.expect_punct()?; |
260 | // check if it start from "`" | 271 | if punct.char != '\'' { |
261 | if !ident.text.starts_with('\'') { | ||
262 | return Err(()); | 272 | return Err(()); |
263 | } | 273 | } |
264 | Ok(ident) | 274 | let ident = self.expect_ident()?; |
275 | |||
276 | Ok(tt::Subtree { | ||
277 | delimiter: None, | ||
278 | token_trees: vec![ | ||
279 | tt::Leaf::Punct(punct.clone()).into(), | ||
280 | tt::Leaf::Ident(ident.clone()).into(), | ||
281 | ], | ||
282 | } | ||
283 | .into()) | ||
265 | } | 284 | } |
266 | 285 | ||
267 | pub(crate) fn expect_fragment( | 286 | pub(crate) fn expect_fragment( |
@@ -274,7 +293,10 @@ impl<'a> TtIter<'a> { | |||
274 | } | 293 | } |
275 | 294 | ||
276 | impl<'a> TreeSink for OffsetTokenSink<'a> { | 295 | impl<'a> TreeSink for OffsetTokenSink<'a> { |
277 | fn token(&mut self, _kind: SyntaxKind, n_tokens: u8) { | 296 | fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) { |
297 | if kind == SyntaxKind::LIFETIME { | ||
298 | n_tokens = 2; | ||
299 | } | ||
278 | for _ in 0..n_tokens { | 300 | for _ in 0..n_tokens { |
279 | self.cursor = self.cursor.bump_subtree(); | 301 | self.cursor = self.cursor.bump_subtree(); |
280 | } | 302 | } |
@@ -286,7 +308,7 @@ impl<'a> TtIter<'a> { | |||
286 | } | 308 | } |
287 | } | 309 | } |
288 | 310 | ||
289 | let buffer = TokenBuffer::new(self.inner.as_slice()); | 311 | let buffer = TokenBuffer::new(&self.inner.as_slice()); |
290 | let mut src = SubtreeTokenSource::new(&buffer); | 312 | let mut src = SubtreeTokenSource::new(&buffer); |
291 | let mut sink = OffsetTokenSink { cursor: buffer.begin(), error: false }; | 313 | let mut sink = OffsetTokenSink { cursor: buffer.begin(), error: false }; |
292 | 314 | ||
@@ -422,7 +444,7 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen | |||
422 | "tt" => input.expect_tt().map(Some).map_err(|()| err!()), | 444 | "tt" => input.expect_tt().map(Some).map_err(|()| err!()), |
423 | "lifetime" => input | 445 | "lifetime" => input |
424 | .expect_lifetime() | 446 | .expect_lifetime() |
425 | .map(|ident| Some(tt::Leaf::Ident(ident.clone()).into())) | 447 | .map(|tt| Some(tt)) |
426 | .map_err(|()| err!("expected lifetime")), | 448 | .map_err(|()| err!("expected lifetime")), |
427 | "literal" => input | 449 | "literal" => input |
428 | .expect_literal() | 450 | .expect_literal() |
diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index 91e324db9..d7866452d 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs | |||
@@ -50,6 +50,26 @@ impl<'a> SubtreeTokenSource<'a> { | |||
50 | } | 50 | } |
51 | 51 | ||
52 | fn get(&self, pos: usize) -> Ref<Option<TtToken>> { | 52 | fn get(&self, pos: usize) -> Ref<Option<TtToken>> { |
53 | fn is_lifetime(c: Cursor) -> Option<(Cursor, SmolStr)> { | ||
54 | let tkn = c.token_tree(); | ||
55 | |||
56 | if let Some(tt::TokenTree::Leaf(tt::Leaf::Punct(punct))) = tkn { | ||
57 | if punct.char == '\'' { | ||
58 | let next = c.bump(); | ||
59 | if let Some(tt::TokenTree::Leaf(tt::Leaf::Ident(ident))) = next.token_tree() { | ||
60 | let res_cursor = next.bump(); | ||
61 | let text = SmolStr::new("'".to_string() + &ident.to_string()); | ||
62 | |||
63 | return Some((res_cursor, text)); | ||
64 | } else { | ||
65 | panic!("Next token must be ident : {:#?}", next.token_tree()); | ||
66 | } | ||
67 | } | ||
68 | } | ||
69 | |||
70 | None | ||
71 | } | ||
72 | |||
53 | if pos < self.cached.borrow().len() { | 73 | if pos < self.cached.borrow().len() { |
54 | return Ref::map(self.cached.borrow(), |c| &c[pos]); | 74 | return Ref::map(self.cached.borrow(), |c| &c[pos]); |
55 | } | 75 | } |
@@ -63,6 +83,12 @@ impl<'a> SubtreeTokenSource<'a> { | |||
63 | continue; | 83 | continue; |
64 | } | 84 | } |
65 | 85 | ||
86 | if let Some((curr, text)) = is_lifetime(cursor) { | ||
87 | cached.push(Some(TtToken { kind: LIFETIME, is_joint_to_next: false, text })); | ||
88 | self.cached_cursor.set(curr); | ||
89 | continue; | ||
90 | } | ||
91 | |||
66 | match cursor.token_tree() { | 92 | match cursor.token_tree() { |
67 | Some(tt::TokenTree::Leaf(leaf)) => { | 93 | Some(tt::TokenTree::Leaf(leaf)) => { |
68 | cached.push(Some(convert_leaf(&leaf))); | 94 | cached.push(Some(convert_leaf(&leaf))); |
@@ -132,27 +158,28 @@ fn convert_literal(l: &tt::Literal) -> TtToken { | |||
132 | let kind = lex_single_syntax_kind(&l.text) | 158 | let kind = lex_single_syntax_kind(&l.text) |
133 | .map(|(kind, _error)| kind) | 159 | .map(|(kind, _error)| kind) |
134 | .filter(|kind| kind.is_literal()) | 160 | .filter(|kind| kind.is_literal()) |
135 | .unwrap_or_else(|| match l.text.as_ref() { | 161 | .unwrap_or_else(|| panic!("Fail to convert given literal {:#?}", &l)); |
136 | "true" => T![true], | ||
137 | "false" => T![false], | ||
138 | _ => panic!("Fail to convert given literal {:#?}", &l), | ||
139 | }); | ||
140 | 162 | ||
141 | TtToken { kind, is_joint_to_next: false, text: l.text.clone() } | 163 | TtToken { kind, is_joint_to_next: false, text: l.text.clone() } |
142 | } | 164 | } |
143 | 165 | ||
144 | fn convert_ident(ident: &tt::Ident) -> TtToken { | 166 | fn convert_ident(ident: &tt::Ident) -> TtToken { |
145 | let kind = if ident.text.starts_with('\'') { | 167 | let kind = match ident.text.as_ref() { |
146 | LIFETIME | 168 | "true" => T![true], |
147 | } else { | 169 | "false" => T![false], |
148 | SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT) | 170 | i if i.starts_with('\'') => LIFETIME, |
171 | _ => SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT), | ||
149 | }; | 172 | }; |
150 | 173 | ||
151 | TtToken { kind, is_joint_to_next: false, text: ident.text.clone() } | 174 | TtToken { kind, is_joint_to_next: false, text: ident.text.clone() } |
152 | } | 175 | } |
153 | 176 | ||
154 | fn convert_punct(p: tt::Punct) -> TtToken { | 177 | fn convert_punct(p: tt::Punct) -> TtToken { |
155 | let kind = SyntaxKind::from_char(p.char).unwrap(); | 178 | let kind = match SyntaxKind::from_char(p.char) { |
179 | None => panic!("{:#?} is not a valid punct", p), | ||
180 | Some(kind) => kind, | ||
181 | }; | ||
182 | |||
156 | let text = { | 183 | let text = { |
157 | let mut buf = [0u8; 4]; | 184 | let mut buf = [0u8; 4]; |
158 | let s: &str = p.char.encode_utf8(&mut buf); | 185 | let s: &str = p.char.encode_utf8(&mut buf); |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 31e9b22e7..2b4390eb2 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -271,7 +271,7 @@ struct RawConvertor<'a> { | |||
271 | inner: std::slice::Iter<'a, RawToken>, | 271 | inner: std::slice::Iter<'a, RawToken>, |
272 | } | 272 | } |
273 | 273 | ||
274 | trait SrcToken { | 274 | trait SrcToken: std::fmt::Debug { |
275 | fn kind(&self) -> SyntaxKind; | 275 | fn kind(&self) -> SyntaxKind; |
276 | 276 | ||
277 | fn to_char(&self) -> Option<char>; | 277 | fn to_char(&self) -> Option<char>; |
@@ -361,8 +361,12 @@ trait TokenConvertor { | |||
361 | Some(next) if next.kind().is_punct() => tt::Spacing::Joint, | 361 | Some(next) if next.kind().is_punct() => tt::Spacing::Joint, |
362 | _ => tt::Spacing::Alone, | 362 | _ => tt::Spacing::Alone, |
363 | }; | 363 | }; |
364 | let char = token.to_char().expect("Token from lexer must be single char"); | 364 | let char = match token.to_char() { |
365 | 365 | Some(c) => c, | |
366 | None => { | ||
367 | panic!("Token from lexer must be single char: token = {:#?}", token); | ||
368 | } | ||
369 | }; | ||
366 | tt::Leaf::from(tt::Punct { char, spacing, id: self.id_alloc().alloc(range) }).into() | 370 | tt::Leaf::from(tt::Punct { char, spacing, id: self.id_alloc().alloc(range) }).into() |
367 | } | 371 | } |
368 | } else { | 372 | } else { |
@@ -372,10 +376,29 @@ trait TokenConvertor { | |||
372 | }; | 376 | }; |
373 | } | 377 | } |
374 | let leaf: tt::Leaf = match k { | 378 | let leaf: tt::Leaf = match k { |
375 | T![true] | T![false] => make_leaf!(Literal), | 379 | T![true] | T![false] => make_leaf!(Ident), |
376 | IDENT | LIFETIME => make_leaf!(Ident), | 380 | IDENT => make_leaf!(Ident), |
377 | k if k.is_keyword() => make_leaf!(Ident), | 381 | k if k.is_keyword() => make_leaf!(Ident), |
378 | k if k.is_literal() => make_leaf!(Literal), | 382 | k if k.is_literal() => make_leaf!(Literal), |
383 | LIFETIME => { | ||
384 | let char_unit = TextUnit::from_usize(1); | ||
385 | let r = TextRange::offset_len(range.start(), char_unit); | ||
386 | let apostrophe = tt::Leaf::from(tt::Punct { | ||
387 | char: '\'', | ||
388 | spacing: tt::Spacing::Joint, | ||
389 | id: self.id_alloc().alloc(r), | ||
390 | }); | ||
391 | result.push(apostrophe.into()); | ||
392 | |||
393 | let r = | ||
394 | TextRange::offset_len(range.start() + char_unit, range.len() - char_unit); | ||
395 | let ident = tt::Leaf::from(tt::Ident { | ||
396 | text: SmolStr::new(&token.to_text()[1..]), | ||
397 | id: self.id_alloc().alloc(r), | ||
398 | }); | ||
399 | result.push(ident.into()); | ||
400 | return; | ||
401 | } | ||
379 | _ => return, | 402 | _ => return, |
380 | }; | 403 | }; |
381 | 404 | ||
@@ -455,6 +478,7 @@ impl Convertor { | |||
455 | } | 478 | } |
456 | } | 479 | } |
457 | 480 | ||
481 | #[derive(Debug)] | ||
458 | enum SynToken { | 482 | enum SynToken { |
459 | Ordiniary(SyntaxToken), | 483 | Ordiniary(SyntaxToken), |
460 | Punch(SyntaxToken, TextUnit), | 484 | Punch(SyntaxToken, TextUnit), |
@@ -592,11 +616,14 @@ fn delim_to_str(d: Option<tt::DelimiterKind>, closing: bool) -> SmolStr { | |||
592 | } | 616 | } |
593 | 617 | ||
594 | impl<'a> TreeSink for TtTreeSink<'a> { | 618 | impl<'a> TreeSink for TtTreeSink<'a> { |
595 | fn token(&mut self, kind: SyntaxKind, n_tokens: u8) { | 619 | fn token(&mut self, kind: SyntaxKind, mut n_tokens: u8) { |
596 | if kind == L_DOLLAR || kind == R_DOLLAR { | 620 | if kind == L_DOLLAR || kind == R_DOLLAR { |
597 | self.cursor = self.cursor.bump_subtree(); | 621 | self.cursor = self.cursor.bump_subtree(); |
598 | return; | 622 | return; |
599 | } | 623 | } |
624 | if kind == LIFETIME { | ||
625 | n_tokens = 2; | ||
626 | } | ||
600 | 627 | ||
601 | let mut last = self.cursor; | 628 | let mut last = self.cursor; |
602 | for _ in 0..n_tokens { | 629 | for _ in 0..n_tokens { |
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs index 5d1274d21..100ed41f2 100644 --- a/crates/ra_mbe/src/tests.rs +++ b/crates/ra_mbe/src/tests.rs | |||
@@ -215,6 +215,33 @@ SUBTREE $ | |||
215 | } | 215 | } |
216 | 216 | ||
217 | #[test] | 217 | #[test] |
218 | fn test_lifetime_split() { | ||
219 | parse_macro( | ||
220 | r#" | ||
221 | macro_rules! foo { | ||
222 | ($($t:tt)*) => { $($t)*} | ||
223 | } | ||
224 | "#, | ||
225 | ) | ||
226 | .assert_expand( | ||
227 | r#"foo!(static bar: &'static str = "hello";);"#, | ||
228 | r#" | ||
229 | SUBTREE $ | ||
230 | IDENT static 17 | ||
231 | IDENT bar 18 | ||
232 | PUNCH : [alone] 19 | ||
233 | PUNCH & [alone] 20 | ||
234 | PUNCH ' [joint] 21 | ||
235 | IDENT static 22 | ||
236 | IDENT str 23 | ||
237 | PUNCH = [alone] 24 | ||
238 | LITERAL "hello" 25 | ||
239 | PUNCH ; [joint] 26 | ||
240 | "#, | ||
241 | ); | ||
242 | } | ||
243 | |||
244 | #[test] | ||
218 | fn test_expr_order() { | 245 | fn test_expr_order() { |
219 | let expanded = parse_macro( | 246 | let expanded = parse_macro( |
220 | r#" | 247 | r#" |
@@ -989,6 +1016,36 @@ fn test_literal() { | |||
989 | } | 1016 | } |
990 | 1017 | ||
991 | #[test] | 1018 | #[test] |
1019 | fn test_boolean_is_ident() { | ||
1020 | parse_macro( | ||
1021 | r#" | ||
1022 | macro_rules! foo { | ||
1023 | ($lit0:literal, $lit1:literal) => { const VALUE: (bool,bool) = ($lit0,$lit1); }; | ||
1024 | } | ||
1025 | "#, | ||
1026 | ) | ||
1027 | .assert_expand( | ||
1028 | r#"foo!(true,false);"#, | ||
1029 | r#" | ||
1030 | SUBTREE $ | ||
1031 | IDENT const 14 | ||
1032 | IDENT VALUE 15 | ||
1033 | PUNCH : [alone] 16 | ||
1034 | SUBTREE () 17 | ||
1035 | IDENT bool 18 | ||
1036 | PUNCH , [alone] 19 | ||
1037 | IDENT bool 20 | ||
1038 | PUNCH = [alone] 21 | ||
1039 | SUBTREE () 22 | ||
1040 | IDENT true 29 | ||
1041 | PUNCH , [joint] 25 | ||
1042 | IDENT false 31 | ||
1043 | PUNCH ; [alone] 28 | ||
1044 | "#, | ||
1045 | ); | ||
1046 | } | ||
1047 | |||
1048 | #[test] | ||
992 | fn test_vis() { | 1049 | fn test_vis() { |
993 | parse_macro( | 1050 | parse_macro( |
994 | r#" | 1051 | r#" |
diff --git a/crates/ra_mbe/src/tt_iter.rs b/crates/ra_mbe/src/tt_iter.rs index 100184e66..46c420718 100644 --- a/crates/ra_mbe/src/tt_iter.rs +++ b/crates/ra_mbe/src/tt_iter.rs | |||
@@ -40,9 +40,11 @@ impl<'a> TtIter<'a> { | |||
40 | } | 40 | } |
41 | } | 41 | } |
42 | 42 | ||
43 | pub(crate) fn expect_literal(&mut self) -> Result<&'a tt::Literal, ()> { | 43 | pub(crate) fn expect_literal(&mut self) -> Result<&'a tt::Leaf, ()> { |
44 | match self.expect_leaf()? { | 44 | let it = self.expect_leaf()?; |
45 | tt::Leaf::Literal(it) => Ok(it), | 45 | match it { |
46 | tt::Leaf::Literal(_) => Ok(it), | ||
47 | tt::Leaf::Ident(ident) if ident.text == "true" || ident.text == "false" => Ok(it), | ||
46 | _ => Err(()), | 48 | _ => Err(()), |
47 | } | 49 | } |
48 | } | 50 | } |
diff --git a/crates/ra_proc_macro/src/lib.rs b/crates/ra_proc_macro/src/lib.rs index b200fd126..004943b9e 100644 --- a/crates/ra_proc_macro/src/lib.rs +++ b/crates/ra_proc_macro/src/lib.rs | |||
@@ -2,7 +2,7 @@ | |||
2 | //! | 2 | //! |
3 | //! We separate proc-macro expanding logic to an extern program to allow | 3 | //! We separate proc-macro expanding logic to an extern program to allow |
4 | //! different implementations (e.g. wasm or dylib loading). And this crate | 4 | //! different implementations (e.g. wasm or dylib loading). And this crate |
5 | //! is used to provide basic infrastructure for communication between two | 5 | //! is used to provide basic infrastructure for communication between two |
6 | //! processes: Client (RA itself), Server (the external program) | 6 | //! processes: Client (RA itself), Server (the external program) |
7 | 7 | ||
8 | mod rpc; | 8 | mod rpc; |
@@ -13,6 +13,7 @@ use process::{ProcMacroProcessSrv, ProcMacroProcessThread}; | |||
13 | use ra_tt::{SmolStr, Subtree}; | 13 | use ra_tt::{SmolStr, Subtree}; |
14 | use std::{ | 14 | use std::{ |
15 | ffi::OsStr, | 15 | ffi::OsStr, |
16 | io, | ||
16 | path::{Path, PathBuf}, | 17 | path::{Path, PathBuf}, |
17 | sync::Arc, | 18 | sync::Arc, |
18 | }; | 19 | }; |
@@ -57,14 +58,10 @@ pub struct ProcMacroClient { | |||
57 | } | 58 | } |
58 | 59 | ||
59 | impl ProcMacroClient { | 60 | impl ProcMacroClient { |
60 | pub fn extern_process<I, S>( | 61 | pub fn extern_process( |
61 | process_path: &Path, | 62 | process_path: PathBuf, |
62 | args: I, | 63 | args: impl IntoIterator<Item = impl AsRef<OsStr>>, |
63 | ) -> Result<ProcMacroClient, std::io::Error> | 64 | ) -> io::Result<ProcMacroClient> { |
64 | where | ||
65 | I: IntoIterator<Item = S>, | ||
66 | S: AsRef<OsStr>, | ||
67 | { | ||
68 | let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?; | 65 | let (thread, process) = ProcMacroProcessSrv::run(process_path, args)?; |
69 | Ok(ProcMacroClient { | 66 | Ok(ProcMacroClient { |
70 | kind: ProcMacroClientKind::Process { process: Arc::new(process), thread }, | 67 | kind: ProcMacroClientKind::Process { process: Arc::new(process), thread }, |
@@ -84,7 +81,7 @@ impl ProcMacroClient { | |||
84 | ProcMacroClientKind::Process { process, .. } => { | 81 | ProcMacroClientKind::Process { process, .. } => { |
85 | let macros = match process.find_proc_macros(dylib_path) { | 82 | let macros = match process.find_proc_macros(dylib_path) { |
86 | Err(err) => { | 83 | Err(err) => { |
87 | eprintln!("Fail to find proc macro. Error: {:#?}", err); | 84 | eprintln!("Failed to find proc macros. Error: {:#?}", err); |
88 | return vec![]; | 85 | return vec![]; |
89 | } | 86 | } |
90 | Ok(macros) => macros, | 87 | Ok(macros) => macros, |
diff --git a/crates/ra_proc_macro/src/msg.rs b/crates/ra_proc_macro/src/msg.rs index aa95bcc8f..95d9b8804 100644 --- a/crates/ra_proc_macro/src/msg.rs +++ b/crates/ra_proc_macro/src/msg.rs | |||
@@ -1,4 +1,4 @@ | |||
1 | //! Defines messages for cross-process message based on `ndjson` wire protocol | 1 | //! Defines messages for cross-process message passing based on `ndjson` wire protocol |
2 | 2 | ||
3 | use std::{ | 3 | use std::{ |
4 | convert::TryFrom, | 4 | convert::TryFrom, |
@@ -31,7 +31,7 @@ macro_rules! impl_try_from_response { | |||
31 | fn try_from(value: Response) -> Result<Self, Self::Error> { | 31 | fn try_from(value: Response) -> Result<Self, Self::Error> { |
32 | match value { | 32 | match value { |
33 | Response::$tag(res) => Ok(res), | 33 | Response::$tag(res) => Ok(res), |
34 | _ => Err("Fail to convert from response"), | 34 | _ => Err(concat!("Failed to convert response to ", stringify!($tag))), |
35 | } | 35 | } |
36 | } | 36 | } |
37 | } | 37 | } |
@@ -53,18 +53,16 @@ pub enum ErrorCode { | |||
53 | ExpansionError, | 53 | ExpansionError, |
54 | } | 54 | } |
55 | 55 | ||
56 | pub trait Message: Sized + Serialize + DeserializeOwned { | 56 | pub trait Message: Serialize + DeserializeOwned { |
57 | fn read(r: &mut impl BufRead) -> io::Result<Option<Self>> { | 57 | fn read(inp: &mut impl BufRead) -> io::Result<Option<Self>> { |
58 | let text = match read_json(r)? { | 58 | Ok(match read_json(inp)? { |
59 | None => return Ok(None), | 59 | None => None, |
60 | Some(text) => text, | 60 | Some(text) => Some(serde_json::from_str(&text)?), |
61 | }; | 61 | }) |
62 | let msg = serde_json::from_str(&text)?; | ||
63 | Ok(Some(msg)) | ||
64 | } | 62 | } |
65 | fn write(self, w: &mut impl Write) -> io::Result<()> { | 63 | fn write(self, out: &mut impl Write) -> io::Result<()> { |
66 | let text = serde_json::to_string(&self)?; | 64 | let text = serde_json::to_string(&self)?; |
67 | write_json(w, &text) | 65 | write_json(out, &text) |
68 | } | 66 | } |
69 | } | 67 | } |
70 | 68 | ||
@@ -73,15 +71,12 @@ impl Message for Response {} | |||
73 | 71 | ||
74 | fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> { | 72 | fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> { |
75 | let mut buf = String::new(); | 73 | let mut buf = String::new(); |
76 | if inp.read_line(&mut buf)? == 0 { | 74 | inp.read_line(&mut buf)?; |
77 | return Ok(None); | 75 | buf.pop(); // Remove traling '\n' |
78 | } | 76 | Ok(match buf.len() { |
79 | // Remove ending '\n' | 77 | 0 => None, |
80 | let buf = &buf[..buf.len() - 1]; | 78 | _ => Some(buf), |
81 | if buf.is_empty() { | 79 | }) |
82 | return Ok(None); | ||
83 | } | ||
84 | Ok(Some(buf.to_string())) | ||
85 | } | 80 | } |
86 | 81 | ||
87 | fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { | 82 | fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { |
diff --git a/crates/ra_proc_macro/src/process.rs b/crates/ra_proc_macro/src/process.rs index f851570bc..5bcdacb48 100644 --- a/crates/ra_proc_macro/src/process.rs +++ b/crates/ra_proc_macro/src/process.rs | |||
@@ -9,7 +9,7 @@ use crate::rpc::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTas | |||
9 | use io::{BufRead, BufReader}; | 9 | use io::{BufRead, BufReader}; |
10 | use std::{ | 10 | use std::{ |
11 | convert::{TryFrom, TryInto}, | 11 | convert::{TryFrom, TryInto}, |
12 | ffi::OsStr, | 12 | ffi::{OsStr, OsString}, |
13 | io::{self, Write}, | 13 | io::{self, Write}, |
14 | path::{Path, PathBuf}, | 14 | path::{Path, PathBuf}, |
15 | process::{Child, Command, Stdio}, | 15 | process::{Child, Command, Stdio}, |
@@ -28,66 +28,11 @@ pub(crate) struct ProcMacroProcessThread { | |||
28 | handle: jod_thread::JoinHandle<()>, | 28 | handle: jod_thread::JoinHandle<()>, |
29 | } | 29 | } |
30 | 30 | ||
31 | struct Task { | ||
32 | req: Request, | ||
33 | result_tx: Sender<Option<Response>>, | ||
34 | } | ||
35 | |||
36 | struct Process { | ||
37 | path: PathBuf, | ||
38 | child: Child, | ||
39 | } | ||
40 | |||
41 | impl Drop for Process { | ||
42 | fn drop(&mut self) { | ||
43 | let _ = self.child.kill(); | ||
44 | } | ||
45 | } | ||
46 | |||
47 | impl Process { | ||
48 | fn run<I, S>(process_path: &Path, args: I) -> Result<Process, io::Error> | ||
49 | where | ||
50 | I: IntoIterator<Item = S>, | ||
51 | S: AsRef<OsStr>, | ||
52 | { | ||
53 | let child = Command::new(process_path.clone()) | ||
54 | .args(args) | ||
55 | .stdin(Stdio::piped()) | ||
56 | .stdout(Stdio::piped()) | ||
57 | .stderr(Stdio::null()) | ||
58 | .spawn()?; | ||
59 | |||
60 | Ok(Process { path: process_path.into(), child }) | ||
61 | } | ||
62 | |||
63 | fn restart(&mut self) -> Result<(), io::Error> { | ||
64 | let _ = self.child.kill(); | ||
65 | self.child = Command::new(self.path.clone()) | ||
66 | .stdin(Stdio::piped()) | ||
67 | .stdout(Stdio::piped()) | ||
68 | .stderr(Stdio::null()) | ||
69 | .spawn()?; | ||
70 | Ok(()) | ||
71 | } | ||
72 | |||
73 | fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> { | ||
74 | let stdin = self.child.stdin.take()?; | ||
75 | let stdout = self.child.stdout.take()?; | ||
76 | let read = BufReader::new(stdout); | ||
77 | |||
78 | Some((stdin, read)) | ||
79 | } | ||
80 | } | ||
81 | |||
82 | impl ProcMacroProcessSrv { | 31 | impl ProcMacroProcessSrv { |
83 | pub fn run<I, S>( | 32 | pub fn run( |
84 | process_path: &Path, | 33 | process_path: PathBuf, |
85 | args: I, | 34 | args: impl IntoIterator<Item = impl AsRef<OsStr>>, |
86 | ) -> Result<(ProcMacroProcessThread, ProcMacroProcessSrv), io::Error> | 35 | ) -> io::Result<(ProcMacroProcessThread, ProcMacroProcessSrv)> { |
87 | where | ||
88 | I: IntoIterator<Item = S>, | ||
89 | S: AsRef<OsStr>, | ||
90 | { | ||
91 | let process = Process::run(process_path, args)?; | 36 | let process = Process::run(process_path, args)?; |
92 | 37 | ||
93 | let (task_tx, task_rx) = bounded(0); | 38 | let (task_tx, task_rx) = bounded(0); |
@@ -197,11 +142,62 @@ fn client_loop(task_rx: Receiver<Task>, mut process: Process) { | |||
197 | } | 142 | } |
198 | } | 143 | } |
199 | 144 | ||
145 | struct Task { | ||
146 | req: Request, | ||
147 | result_tx: Sender<Option<Response>>, | ||
148 | } | ||
149 | |||
150 | struct Process { | ||
151 | path: PathBuf, | ||
152 | args: Vec<OsString>, | ||
153 | child: Child, | ||
154 | } | ||
155 | |||
156 | impl Drop for Process { | ||
157 | fn drop(&mut self) { | ||
158 | let _ = self.child.kill(); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | impl Process { | ||
163 | fn run( | ||
164 | path: PathBuf, | ||
165 | args: impl IntoIterator<Item = impl AsRef<OsStr>>, | ||
166 | ) -> io::Result<Process> { | ||
167 | let args = args.into_iter().map(|s| s.as_ref().into()).collect(); | ||
168 | let child = mk_child(&path, &args)?; | ||
169 | Ok(Process { path, args, child }) | ||
170 | } | ||
171 | |||
172 | fn restart(&mut self) -> io::Result<()> { | ||
173 | let _ = self.child.kill(); | ||
174 | self.child = mk_child(&self.path, &self.args)?; | ||
175 | Ok(()) | ||
176 | } | ||
177 | |||
178 | fn stdio(&mut self) -> Option<(impl Write, impl BufRead)> { | ||
179 | let stdin = self.child.stdin.take()?; | ||
180 | let stdout = self.child.stdout.take()?; | ||
181 | let read = BufReader::new(stdout); | ||
182 | |||
183 | Some((stdin, read)) | ||
184 | } | ||
185 | } | ||
186 | |||
187 | fn mk_child(path: &Path, args: impl IntoIterator<Item = impl AsRef<OsStr>>) -> io::Result<Child> { | ||
188 | Command::new(&path) | ||
189 | .args(args) | ||
190 | .stdin(Stdio::piped()) | ||
191 | .stdout(Stdio::piped()) | ||
192 | .stderr(Stdio::inherit()) | ||
193 | .spawn() | ||
194 | } | ||
195 | |||
200 | fn send_request( | 196 | fn send_request( |
201 | mut writer: &mut impl Write, | 197 | mut writer: &mut impl Write, |
202 | mut reader: &mut impl BufRead, | 198 | mut reader: &mut impl BufRead, |
203 | req: Request, | 199 | req: Request, |
204 | ) -> Result<Option<Response>, io::Error> { | 200 | ) -> io::Result<Option<Response>> { |
205 | req.write(&mut writer)?; | 201 | req.write(&mut writer)?; |
206 | Ok(Response::read(&mut reader)?) | 202 | Ok(Response::read(&mut reader)?) |
207 | } | 203 | } |
diff --git a/crates/ra_proc_macro/src/rpc.rs b/crates/ra_proc_macro/src/rpc.rs index 66b3f55db..4ce485926 100644 --- a/crates/ra_proc_macro/src/rpc.rs +++ b/crates/ra_proc_macro/src/rpc.rs | |||
@@ -1,9 +1,9 @@ | |||
1 | //! Data struture serialization related stuffs for RPC | 1 | //! Data struture serialization related stuff for RPC |
2 | //! | 2 | //! |
3 | //! Define all necessary rpc serialization data structure, | 3 | //! Defines all necessary rpc serialization data structures, |
4 | //! which include ra_tt related data and some task messages. | 4 | //! which includes `ra_tt` related data and some task messages. |
5 | //! Although adding Serialize and Deserialize trait to ra_tt directly seem to be much easier, | 5 | //! Although adding `Serialize` and `Deserialize` traits to `ra_tt` directly seems |
6 | //! we deliberately duplicate the ra_tt struct with #[serde(with = "XXDef")] | 6 | //! to be much easier, we deliberately duplicate `ra_tt` structs with `#[serde(with = "XXDef")]` |
7 | //! for separation of code responsibility. | 7 | //! for separation of code responsibility. |
8 | 8 | ||
9 | use ra_tt::{ | 9 | use ra_tt::{ |
@@ -34,15 +34,15 @@ pub struct ListMacrosResult { | |||
34 | pub struct ExpansionTask { | 34 | pub struct ExpansionTask { |
35 | /// Argument of macro call. | 35 | /// Argument of macro call. |
36 | /// | 36 | /// |
37 | /// In custom derive that would be a struct or enum; in attribute-like macro - underlying | 37 | /// In custom derive this will be a struct or enum; in attribute-like macro - underlying |
38 | /// item; in function-like macro - the macro body. | 38 | /// item; in function-like macro - the macro body. |
39 | #[serde(with = "SubtreeDef")] | 39 | #[serde(with = "SubtreeDef")] |
40 | pub macro_body: Subtree, | 40 | pub macro_body: Subtree, |
41 | 41 | ||
42 | /// Names of macros to expand. | 42 | /// Name of macro to expand. |
43 | /// | 43 | /// |
44 | /// In custom derive those are names of derived traits (`Serialize`, `Getters`, etc.). In | 44 | /// In custom derive this is the name of the derived trait (`Serialize`, `Getters`, etc.). |
45 | /// attribute-like and functiona-like macros - single name of macro itself (`show_streams`). | 45 | /// In attribute-like and function-like macros - single name of macro itself (`show_streams`). |
46 | pub macro_name: String, | 46 | pub macro_name: String, |
47 | 47 | ||
48 | /// Possible attributes for the attribute-like macros. | 48 | /// Possible attributes for the attribute-like macros. |
diff --git a/crates/ra_proc_macro_srv/src/cli.rs b/crates/ra_proc_macro_srv/src/cli.rs index c771f2b38..7282e5b9b 100644 --- a/crates/ra_proc_macro_srv/src/cli.rs +++ b/crates/ra_proc_macro_srv/src/cli.rs | |||
@@ -2,55 +2,36 @@ | |||
2 | 2 | ||
3 | use crate::{expand_task, list_macros}; | 3 | use crate::{expand_task, list_macros}; |
4 | use ra_proc_macro::msg::{self, Message}; | 4 | use ra_proc_macro::msg::{self, Message}; |
5 | |||
6 | use std::io; | 5 | use std::io; |
7 | 6 | ||
8 | fn read_request() -> Result<Option<msg::Request>, io::Error> { | 7 | pub fn run() -> io::Result<()> { |
9 | let stdin = io::stdin(); | 8 | while let Some(req) = read_request()? { |
10 | let mut stdin = stdin.lock(); | 9 | let res = match req { |
11 | msg::Request::read(&mut stdin) | 10 | msg::Request::ListMacro(task) => Ok(msg::Response::ListMacro(list_macros(&task))), |
12 | } | 11 | msg::Request::ExpansionMacro(task) => { |
13 | 12 | expand_task(&task).map(msg::Response::ExpansionMacro) | |
14 | fn write_response(res: Result<msg::Response, String>) -> Result<(), io::Error> { | ||
15 | let msg: msg::Response = match res { | ||
16 | Ok(res) => res, | ||
17 | Err(err) => msg::Response::Error(msg::ResponseError { | ||
18 | code: msg::ErrorCode::ExpansionError, | ||
19 | message: err, | ||
20 | }), | ||
21 | }; | ||
22 | |||
23 | let stdout = io::stdout(); | ||
24 | let mut stdout = stdout.lock(); | ||
25 | msg.write(&mut stdout) | ||
26 | } | ||
27 | |||
28 | pub fn run() { | ||
29 | loop { | ||
30 | let req = match read_request() { | ||
31 | Err(err) => { | ||
32 | eprintln!("Read message error on ra_proc_macro_srv: {}", err.to_string()); | ||
33 | continue; | ||
34 | } | 13 | } |
35 | Ok(None) => continue, | ||
36 | Ok(Some(req)) => req, | ||
37 | }; | 14 | }; |
38 | 15 | ||
39 | match req { | 16 | let msg = res.unwrap_or_else(|err| { |
40 | msg::Request::ListMacro(task) => { | 17 | msg::Response::Error(msg::ResponseError { |
41 | if let Err(err) = | 18 | code: msg::ErrorCode::ExpansionError, |
42 | write_response(list_macros(&task).map(|it| msg::Response::ListMacro(it))) | 19 | message: err, |
43 | { | 20 | }) |
44 | eprintln!("Write message error on list macro: {}", err); | 21 | }); |
45 | } | 22 | |
46 | } | 23 | if let Err(err) = write_response(msg) { |
47 | msg::Request::ExpansionMacro(task) => { | 24 | eprintln!("Write message error: {}", err); |
48 | if let Err(err) = | ||
49 | write_response(expand_task(&task).map(|it| msg::Response::ExpansionMacro(it))) | ||
50 | { | ||
51 | eprintln!("Write message error on expansion macro: {}", err); | ||
52 | } | ||
53 | } | ||
54 | } | 25 | } |
55 | } | 26 | } |
27 | |||
28 | Ok(()) | ||
29 | } | ||
30 | |||
31 | fn read_request() -> io::Result<Option<msg::Request>> { | ||
32 | msg::Request::read(&mut io::stdin().lock()) | ||
33 | } | ||
34 | |||
35 | fn write_response(msg: msg::Response) -> io::Result<()> { | ||
36 | msg.write(&mut io::stdout().lock()) | ||
56 | } | 37 | } |
diff --git a/crates/ra_proc_macro_srv/src/dylib.rs b/crates/ra_proc_macro_srv/src/dylib.rs index 16bd7466e..d202eb0fd 100644 --- a/crates/ra_proc_macro_srv/src/dylib.rs +++ b/crates/ra_proc_macro_srv/src/dylib.rs | |||
@@ -9,43 +9,37 @@ use libloading::Library; | |||
9 | use memmap::Mmap; | 9 | use memmap::Mmap; |
10 | use ra_proc_macro::ProcMacroKind; | 10 | use ra_proc_macro::ProcMacroKind; |
11 | 11 | ||
12 | use std::io::Error as IoError; | 12 | use std::io; |
13 | use std::io::ErrorKind as IoErrorKind; | ||
14 | 13 | ||
15 | const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; | 14 | const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; |
16 | 15 | ||
17 | fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> IoError { | 16 | fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> io::Error { |
18 | IoError::new(IoErrorKind::InvalidData, e) | 17 | io::Error::new(io::ErrorKind::InvalidData, e) |
19 | } | 18 | } |
20 | 19 | ||
21 | fn is_derive_registrar_symbol(symbol: &str) -> bool { | 20 | fn is_derive_registrar_symbol(symbol: &str) -> bool { |
22 | symbol.contains(NEW_REGISTRAR_SYMBOL) | 21 | symbol.contains(NEW_REGISTRAR_SYMBOL) |
23 | } | 22 | } |
24 | 23 | ||
25 | fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { | 24 | fn find_registrar_symbol(file: &Path) -> io::Result<Option<String>> { |
26 | let file = File::open(file)?; | 25 | let file = File::open(file)?; |
27 | let buffer = unsafe { Mmap::map(&file)? }; | 26 | let buffer = unsafe { Mmap::map(&file)? }; |
28 | let object = Object::parse(&buffer).map_err(invalid_data_err)?; | 27 | let object = Object::parse(&buffer).map_err(invalid_data_err)?; |
29 | 28 | ||
30 | match object { | 29 | let name = match object { |
31 | Object::Elf(elf) => { | 30 | Object::Elf(elf) => { |
32 | let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; | 31 | let symbols = elf.dynstrtab.to_vec().map_err(invalid_data_err)?; |
33 | let name = | 32 | symbols.into_iter().find(|s| is_derive_registrar_symbol(s)).map(&str::to_owned) |
34 | symbols.iter().find(|s| is_derive_registrar_symbol(s)).map(|s| s.to_string()); | ||
35 | Ok(name) | ||
36 | } | ||
37 | Object::PE(pe) => { | ||
38 | let name = pe | ||
39 | .exports | ||
40 | .iter() | ||
41 | .flat_map(|s| s.name) | ||
42 | .find(|s| is_derive_registrar_symbol(s)) | ||
43 | .map(|s| s.to_string()); | ||
44 | Ok(name) | ||
45 | } | 33 | } |
34 | Object::PE(pe) => pe | ||
35 | .exports | ||
36 | .iter() | ||
37 | .flat_map(|s| s.name) | ||
38 | .find(|s| is_derive_registrar_symbol(s)) | ||
39 | .map(&str::to_owned), | ||
46 | Object::Mach(Mach::Binary(binary)) => { | 40 | Object::Mach(Mach::Binary(binary)) => { |
47 | let exports = binary.exports().map_err(invalid_data_err)?; | 41 | let exports = binary.exports().map_err(invalid_data_err)?; |
48 | let name = exports | 42 | exports |
49 | .iter() | 43 | .iter() |
50 | .map(|s| { | 44 | .map(|s| { |
51 | // In macos doc: | 45 | // In macos doc: |
@@ -59,11 +53,11 @@ fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { | |||
59 | } | 53 | } |
60 | }) | 54 | }) |
61 | .find(|s| is_derive_registrar_symbol(s)) | 55 | .find(|s| is_derive_registrar_symbol(s)) |
62 | .map(|s| s.to_string()); | 56 | .map(&str::to_owned) |
63 | Ok(name) | ||
64 | } | 57 | } |
65 | _ => Ok(None), | 58 | _ => return Ok(None), |
66 | } | 59 | }; |
60 | return Ok(name); | ||
67 | } | 61 | } |
68 | 62 | ||
69 | /// Loads dynamic library in platform dependent manner. | 63 | /// Loads dynamic library in platform dependent manner. |
@@ -93,15 +87,16 @@ fn load_library(file: &Path) -> Result<Library, libloading::Error> { | |||
93 | } | 87 | } |
94 | 88 | ||
95 | struct ProcMacroLibraryLibloading { | 89 | struct ProcMacroLibraryLibloading { |
96 | // Hold the dylib to prevent it for unloadeding | 90 | // Hold the dylib to prevent it from unloading |
97 | _lib: Library, | 91 | _lib: Library, |
98 | exported_macros: Vec<bridge::client::ProcMacro>, | 92 | exported_macros: Vec<bridge::client::ProcMacro>, |
99 | } | 93 | } |
100 | 94 | ||
101 | impl ProcMacroLibraryLibloading { | 95 | impl ProcMacroLibraryLibloading { |
102 | fn open(file: &Path) -> Result<Self, IoError> { | 96 | fn open(file: &Path) -> io::Result<Self> { |
103 | let symbol_name = find_registrar_symbol(file)? | 97 | let symbol_name = find_registrar_symbol(file)?.ok_or_else(|| { |
104 | .ok_or(invalid_data_err(format!("Cannot find registrar symbol in file {:?}", file)))?; | 98 | invalid_data_err(format!("Cannot find registrar symbol in file {}", file.display())) |
99 | })?; | ||
105 | 100 | ||
106 | let lib = load_library(file).map_err(invalid_data_err)?; | 101 | let lib = load_library(file).map_err(invalid_data_err)?; |
107 | let exported_macros = { | 102 | let exported_macros = { |
@@ -121,18 +116,16 @@ pub struct Expander { | |||
121 | } | 116 | } |
122 | 117 | ||
123 | impl Expander { | 118 | impl Expander { |
124 | pub fn new<P: AsRef<Path>>(lib: &P) -> Result<Expander, String> { | 119 | pub fn new(lib: &Path) -> Result<Expander, String> { |
125 | let mut libs = vec![]; | 120 | // Some libraries for dynamic loading require canonicalized path even when it is |
126 | /* Some libraries for dynamic loading require canonicalized path (even when it is | 121 | // already absolute |
127 | already absolute | 122 | let lib = lib |
128 | */ | 123 | .canonicalize() |
129 | let lib = | 124 | .unwrap_or_else(|err| panic!("Cannot canonicalize {}: {:?}", lib.display(), err)); |
130 | lib.as_ref().canonicalize().expect(&format!("Cannot canonicalize {:?}", lib.as_ref())); | ||
131 | 125 | ||
132 | let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?; | 126 | let library = ProcMacroLibraryImpl::open(&lib).map_err(|e| e.to_string())?; |
133 | libs.push(library); | ||
134 | 127 | ||
135 | Ok(Expander { libs }) | 128 | Ok(Expander { libs: vec![library] }) |
136 | } | 129 | } |
137 | 130 | ||
138 | pub fn expand( | 131 | pub fn expand( |
@@ -176,7 +169,6 @@ impl Expander { | |||
176 | parsed_attributes, | 169 | parsed_attributes, |
177 | parsed_body, | 170 | parsed_body, |
178 | ); | 171 | ); |
179 | |||
180 | return res.map(|it| it.subtree); | 172 | return res.map(|it| it.subtree); |
181 | } | 173 | } |
182 | _ => continue, | 174 | _ => continue, |
@@ -187,26 +179,21 @@ impl Expander { | |||
187 | Err(bridge::PanicMessage::String("Nothing to expand".to_string())) | 179 | Err(bridge::PanicMessage::String("Nothing to expand".to_string())) |
188 | } | 180 | } |
189 | 181 | ||
190 | pub fn list_macros(&self) -> Result<Vec<(String, ProcMacroKind)>, bridge::PanicMessage> { | 182 | pub fn list_macros(&self) -> Vec<(String, ProcMacroKind)> { |
191 | let mut result = vec![]; | 183 | self.libs |
192 | 184 | .iter() | |
193 | for lib in &self.libs { | 185 | .flat_map(|it| &it.exported_macros) |
194 | for proc_macro in &lib.exported_macros { | 186 | .map(|proc_macro| match proc_macro { |
195 | let res = match proc_macro { | 187 | bridge::client::ProcMacro::CustomDerive { trait_name, .. } => { |
196 | bridge::client::ProcMacro::CustomDerive { trait_name, .. } => { | 188 | (trait_name.to_string(), ProcMacroKind::CustomDerive) |
197 | (trait_name.to_string(), ProcMacroKind::CustomDerive) | 189 | } |
198 | } | 190 | bridge::client::ProcMacro::Bang { name, .. } => { |
199 | bridge::client::ProcMacro::Bang { name, .. } => { | 191 | (name.to_string(), ProcMacroKind::FuncLike) |
200 | (name.to_string(), ProcMacroKind::FuncLike) | 192 | } |
201 | } | 193 | bridge::client::ProcMacro::Attr { name, .. } => { |
202 | bridge::client::ProcMacro::Attr { name, .. } => { | 194 | (name.to_string(), ProcMacroKind::Attr) |
203 | (name.to_string(), ProcMacroKind::Attr) | 195 | } |
204 | } | 196 | }) |
205 | }; | 197 | .collect() |
206 | result.push(res); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | Ok(result) | ||
211 | } | 198 | } |
212 | } | 199 | } |
diff --git a/crates/ra_proc_macro_srv/src/lib.rs b/crates/ra_proc_macro_srv/src/lib.rs index c62b0ed89..3aca859db 100644 --- a/crates/ra_proc_macro_srv/src/lib.rs +++ b/crates/ra_proc_macro_srv/src/lib.rs | |||
@@ -3,10 +3,10 @@ | |||
3 | //! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code. | 3 | //! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code. |
4 | //! The general idea here is based on https://github.com/fedochet/rust-proc-macro-expander. | 4 | //! The general idea here is based on https://github.com/fedochet/rust-proc-macro-expander. |
5 | //! | 5 | //! |
6 | //! But we change some several design for fitting RA needs: | 6 | //! But we adapt it to better fit RA needs: |
7 | //! | 7 | //! |
8 | //! * We use `ra_tt` for proc-macro `TokenStream` server, it is easy to manipute and interact with | 8 | //! * We use `ra_tt` for proc-macro `TokenStream` server, it is easier to manipulate and interact with |
9 | //! RA then proc-macro2 token stream. | 9 | //! RA than `proc-macro2` token stream. |
10 | //! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable` | 10 | //! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable` |
11 | //! rustc rather than `unstable`. (Although in gerenal ABI compatibility is still an issue) | 11 | //! rustc rather than `unstable`. (Although in gerenal ABI compatibility is still an issue) |
12 | 12 | ||
@@ -21,36 +21,28 @@ mod dylib; | |||
21 | 21 | ||
22 | use proc_macro::bridge::client::TokenStream; | 22 | use proc_macro::bridge::client::TokenStream; |
23 | use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; | 23 | use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; |
24 | use std::path::Path; | ||
24 | 25 | ||
25 | pub(crate) fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> { | 26 | pub(crate) fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> { |
26 | let expander = dylib::Expander::new(&task.lib) | 27 | let expander = create_expander(&task.lib); |
27 | .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib)); | ||
28 | 28 | ||
29 | match expander.expand(&task.macro_name, &task.macro_body, task.attributes.as_ref()) { | 29 | match expander.expand(&task.macro_name, &task.macro_body, task.attributes.as_ref()) { |
30 | Ok(expansion) => Ok(ExpansionResult { expansion }), | 30 | Ok(expansion) => Ok(ExpansionResult { expansion }), |
31 | Err(msg) => { | 31 | Err(msg) => { |
32 | let reason = format!( | 32 | Err(format!("Cannot perform expansion for {}: error {:?}", &task.macro_name, msg)) |
33 | "Cannot perform expansion for {}: error {:?}!", | ||
34 | &task.macro_name, | ||
35 | msg.as_str() | ||
36 | ); | ||
37 | Err(reason) | ||
38 | } | 33 | } |
39 | } | 34 | } |
40 | } | 35 | } |
41 | 36 | ||
42 | pub(crate) fn list_macros(task: &ListMacrosTask) -> Result<ListMacrosResult, String> { | 37 | pub(crate) fn list_macros(task: &ListMacrosTask) -> ListMacrosResult { |
43 | let expander = dylib::Expander::new(&task.lib) | 38 | let expander = create_expander(&task.lib); |
44 | .expect(&format!("Cannot expand with provided libraries: ${:?}", &task.lib)); | ||
45 | 39 | ||
46 | match expander.list_macros() { | 40 | ListMacrosResult { macros: expander.list_macros() } |
47 | Ok(macros) => Ok(ListMacrosResult { macros }), | 41 | } |
48 | Err(msg) => { | 42 | |
49 | let reason = | 43 | fn create_expander(lib: &Path) -> dylib::Expander { |
50 | format!("Cannot perform expansion for {:?}: error {:?}!", &task.lib, msg.as_str()); | 44 | dylib::Expander::new(lib) |
51 | Err(reason) | 45 | .unwrap_or_else(|err| panic!("Cannot create expander for {}: {:?}", lib.display(), err)) |
52 | } | ||
53 | } | ||
54 | } | 46 | } |
55 | 47 | ||
56 | pub mod cli; | 48 | pub mod cli; |
diff --git a/crates/ra_proc_macro_srv/src/rustc_server.rs b/crates/ra_proc_macro_srv/src/rustc_server.rs index ec0d35692..f481d70b2 100644 --- a/crates/ra_proc_macro_srv/src/rustc_server.rs +++ b/crates/ra_proc_macro_srv/src/rustc_server.rs | |||
@@ -6,7 +6,7 @@ | |||
6 | //! The original idea from fedochet is using proc-macro2 as backend, | 6 | //! The original idea from fedochet is using proc-macro2 as backend, |
7 | //! we use ra_tt instead for better intergation with RA. | 7 | //! we use ra_tt instead for better intergation with RA. |
8 | //! | 8 | //! |
9 | //! FIXME: No span and source file informatin is implemented yet | 9 | //! FIXME: No span and source file information is implemented yet |
10 | 10 | ||
11 | use crate::proc_macro::bridge::{self, server}; | 11 | use crate::proc_macro::bridge::{self, server}; |
12 | use ra_tt as tt; | 12 | use ra_tt as tt; |
@@ -76,7 +76,16 @@ impl Extend<TokenTree> for TokenStream { | |||
76 | impl Extend<TokenStream> for TokenStream { | 76 | impl Extend<TokenStream> for TokenStream { |
77 | fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { | 77 | fn extend<I: IntoIterator<Item = TokenStream>>(&mut self, streams: I) { |
78 | for item in streams { | 78 | for item in streams { |
79 | self.subtree.token_trees.extend(&mut item.into_iter()) | 79 | for tkn in item { |
80 | match tkn { | ||
81 | tt::TokenTree::Subtree(subtree) if subtree.delimiter.is_none() => { | ||
82 | self.subtree.token_trees.extend(subtree.token_trees); | ||
83 | } | ||
84 | _ => { | ||
85 | self.subtree.token_trees.push(tkn); | ||
86 | } | ||
87 | } | ||
88 | } | ||
80 | } | 89 | } |
81 | } | 90 | } |
82 | } | 91 | } |
diff --git a/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt b/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt index 24507d98d..1f5d940fa 100644 --- a/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt +++ b/crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt | |||
@@ -25,8 +25,7 @@ SUBTREE $ | |||
25 | SUBTREE () 4294967295 | 25 | SUBTREE () 4294967295 |
26 | IDENT feature 4294967295 | 26 | IDENT feature 4294967295 |
27 | PUNCH = [alone] 4294967295 | 27 | PUNCH = [alone] 4294967295 |
28 | SUBTREE $ | 28 | LITERAL "cargo-clippy" 0 |
29 | LITERAL "cargo-clippy" 0 | ||
30 | PUNCH , [alone] 4294967295 | 29 | PUNCH , [alone] 4294967295 |
31 | IDENT allow 4294967295 | 30 | IDENT allow 4294967295 |
32 | SUBTREE () 4294967295 | 31 | SUBTREE () 4294967295 |
diff --git a/crates/ra_proc_macro_srv/src/tests/utils.rs b/crates/ra_proc_macro_srv/src/tests/utils.rs index 1ee409449..2139ec7a4 100644 --- a/crates/ra_proc_macro_srv/src/tests/utils.rs +++ b/crates/ra_proc_macro_srv/src/tests/utils.rs | |||
@@ -60,6 +60,6 @@ pub fn list(crate_name: &str, version: &str) -> Vec<String> { | |||
60 | let path = fixtures::dylib_path(crate_name, version); | 60 | let path = fixtures::dylib_path(crate_name, version); |
61 | let task = ListMacrosTask { lib: path }; | 61 | let task = ListMacrosTask { lib: path }; |
62 | 62 | ||
63 | let res = list_macros(&task).unwrap(); | 63 | let res = list_macros(&task); |
64 | res.macros.into_iter().map(|(name, kind)| format!("{} [{:?}]", name, kind)).collect() | 64 | res.macros.into_iter().map(|(name, kind)| format!("{} [{:?}]", name, kind)).collect() |
65 | } | 65 | } |
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs index b50cda06f..0613310f1 100644 --- a/crates/ra_project_model/src/cargo_workspace.rs +++ b/crates/ra_project_model/src/cargo_workspace.rs | |||
@@ -141,6 +141,11 @@ impl CargoWorkspace { | |||
141 | cargo_toml: &Path, | 141 | cargo_toml: &Path, |
142 | cargo_features: &CargoConfig, | 142 | cargo_features: &CargoConfig, |
143 | ) -> Result<CargoWorkspace> { | 143 | ) -> Result<CargoWorkspace> { |
144 | let _ = Command::new(cargo_binary()) | ||
145 | .arg("--version") | ||
146 | .status() | ||
147 | .context("failed to run `cargo --version`, is `cargo` in PATH?")?; | ||
148 | |||
144 | let mut meta = MetadataCommand::new(); | 149 | let mut meta = MetadataCommand::new(); |
145 | meta.manifest_path(cargo_toml); | 150 | meta.manifest_path(cargo_toml); |
146 | if cargo_features.all_features { | 151 | if cargo_features.all_features { |
@@ -303,8 +308,7 @@ pub fn load_extern_resources( | |||
303 | if message.target.kind.contains(&"proc-macro".to_string()) { | 308 | if message.target.kind.contains(&"proc-macro".to_string()) { |
304 | let package_id = message.package_id; | 309 | let package_id = message.package_id; |
305 | // Skip rmeta file | 310 | // Skip rmeta file |
306 | if let Some(filename) = | 311 | if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) |
307 | message.filenames.iter().filter(|name| is_dylib(name)).next() | ||
308 | { | 312 | { |
309 | res.proc_dylib_paths.insert(package_id, filename.clone()); | 313 | res.proc_dylib_paths.insert(package_id, filename.clone()); |
310 | } | 314 | } |
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs index ea41bf85d..06df8495c 100644 --- a/crates/ra_syntax/src/algo.rs +++ b/crates/ra_syntax/src/algo.rs | |||
@@ -10,8 +10,8 @@ use ra_text_edit::TextEditBuilder; | |||
10 | use rustc_hash::FxHashMap; | 10 | use rustc_hash::FxHashMap; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, SyntaxToken, | 13 | AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxNodePtr, |
14 | TextRange, TextUnit, | 14 | SyntaxToken, TextRange, TextUnit, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | /// Returns ancestors of the node at the offset, sorted by length. This should | 17 | /// Returns ancestors of the node at the offset, sorted by length. This should |
@@ -90,6 +90,10 @@ pub fn neighbor<T: AstNode>(me: &T, direction: Direction) -> Option<T> { | |||
90 | me.syntax().siblings(direction).skip(1).find_map(T::cast) | 90 | me.syntax().siblings(direction).skip(1).find_map(T::cast) |
91 | } | 91 | } |
92 | 92 | ||
93 | pub fn has_errors(node: &SyntaxNode) -> bool { | ||
94 | node.children().any(|it| it.kind() == SyntaxKind::ERROR) | ||
95 | } | ||
96 | |||
93 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | 97 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] |
94 | pub enum InsertPosition<T> { | 98 | pub enum InsertPosition<T> { |
95 | First, | 99 | First, |
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs index 9e5411ee5..26e4576ff 100644 --- a/crates/ra_syntax/src/ast/edit.rs +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -307,7 +307,11 @@ impl ast::UseTree { | |||
307 | 307 | ||
308 | fn split_path_prefix(prefix: &ast::Path) -> Option<ast::Path> { | 308 | fn split_path_prefix(prefix: &ast::Path) -> Option<ast::Path> { |
309 | let parent = prefix.parent_path()?; | 309 | let parent = prefix.parent_path()?; |
310 | let mut res = make::path_unqualified(parent.segment()?); | 310 | let segment = parent.segment()?; |
311 | if algo::has_errors(segment.syntax()) { | ||
312 | return None; | ||
313 | } | ||
314 | let mut res = make::path_unqualified(segment); | ||
311 | for p in iter::successors(parent.parent_path(), |it| it.parent_path()) { | 315 | for p in iter::successors(parent.parent_path(), |it| it.parent_path()) { |
312 | res = make::path_qualified(res, p.segment()?); | 316 | res = make::path_qualified(res, p.segment()?); |
313 | } | 317 | } |
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 188f0df96..2cb3ad011 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs | |||
@@ -10,17 +10,6 @@ use crate::{ | |||
10 | pub struct SourceFile { | 10 | pub struct SourceFile { |
11 | pub(crate) syntax: SyntaxNode, | 11 | pub(crate) syntax: SyntaxNode, |
12 | } | 12 | } |
13 | impl AstNode for SourceFile { | ||
14 | fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE } | ||
15 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
16 | if Self::can_cast(syntax.kind()) { | ||
17 | Some(Self { syntax }) | ||
18 | } else { | ||
19 | None | ||
20 | } | ||
21 | } | ||
22 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
23 | } | ||
24 | impl ast::ModuleItemOwner for SourceFile {} | 13 | impl ast::ModuleItemOwner for SourceFile {} |
25 | impl ast::AttrsOwner for SourceFile {} | 14 | impl ast::AttrsOwner for SourceFile {} |
26 | impl SourceFile { | 15 | impl SourceFile { |
@@ -31,17 +20,6 @@ impl SourceFile { | |||
31 | pub struct FnDef { | 20 | pub struct FnDef { |
32 | pub(crate) syntax: SyntaxNode, | 21 | pub(crate) syntax: SyntaxNode, |
33 | } | 22 | } |
34 | impl AstNode for FnDef { | ||
35 | fn can_cast(kind: SyntaxKind) -> bool { kind == FN_DEF } | ||
36 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
37 | if Self::can_cast(syntax.kind()) { | ||
38 | Some(Self { syntax }) | ||
39 | } else { | ||
40 | None | ||
41 | } | ||
42 | } | ||
43 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
44 | } | ||
45 | impl ast::VisibilityOwner for FnDef {} | 23 | impl ast::VisibilityOwner for FnDef {} |
46 | impl ast::NameOwner for FnDef {} | 24 | impl ast::NameOwner for FnDef {} |
47 | impl ast::TypeParamsOwner for FnDef {} | 25 | impl ast::TypeParamsOwner for FnDef {} |
@@ -64,17 +42,6 @@ impl FnDef { | |||
64 | pub struct RetType { | 42 | pub struct RetType { |
65 | pub(crate) syntax: SyntaxNode, | 43 | pub(crate) syntax: SyntaxNode, |
66 | } | 44 | } |
67 | impl AstNode for RetType { | ||
68 | fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE } | ||
69 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
70 | if Self::can_cast(syntax.kind()) { | ||
71 | Some(Self { syntax }) | ||
72 | } else { | ||
73 | None | ||
74 | } | ||
75 | } | ||
76 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
77 | } | ||
78 | impl RetType { | 45 | impl RetType { |
79 | pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) } | 46 | pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) } |
80 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | 47 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } |
@@ -84,17 +51,6 @@ impl RetType { | |||
84 | pub struct StructDef { | 51 | pub struct StructDef { |
85 | pub(crate) syntax: SyntaxNode, | 52 | pub(crate) syntax: SyntaxNode, |
86 | } | 53 | } |
87 | impl AstNode for StructDef { | ||
88 | fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT_DEF } | ||
89 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
90 | if Self::can_cast(syntax.kind()) { | ||
91 | Some(Self { syntax }) | ||
92 | } else { | ||
93 | None | ||
94 | } | ||
95 | } | ||
96 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
97 | } | ||
98 | impl ast::VisibilityOwner for StructDef {} | 54 | impl ast::VisibilityOwner for StructDef {} |
99 | impl ast::NameOwner for StructDef {} | 55 | impl ast::NameOwner for StructDef {} |
100 | impl ast::TypeParamsOwner for StructDef {} | 56 | impl ast::TypeParamsOwner for StructDef {} |
@@ -110,17 +66,6 @@ impl StructDef { | |||
110 | pub struct UnionDef { | 66 | pub struct UnionDef { |
111 | pub(crate) syntax: SyntaxNode, | 67 | pub(crate) syntax: SyntaxNode, |
112 | } | 68 | } |
113 | impl AstNode for UnionDef { | ||
114 | fn can_cast(kind: SyntaxKind) -> bool { kind == UNION_DEF } | ||
115 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
116 | if Self::can_cast(syntax.kind()) { | ||
117 | Some(Self { syntax }) | ||
118 | } else { | ||
119 | None | ||
120 | } | ||
121 | } | ||
122 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
123 | } | ||
124 | impl ast::VisibilityOwner for UnionDef {} | 69 | impl ast::VisibilityOwner for UnionDef {} |
125 | impl ast::NameOwner for UnionDef {} | 70 | impl ast::NameOwner for UnionDef {} |
126 | impl ast::TypeParamsOwner for UnionDef {} | 71 | impl ast::TypeParamsOwner for UnionDef {} |
@@ -137,17 +82,6 @@ impl UnionDef { | |||
137 | pub struct RecordFieldDefList { | 82 | pub struct RecordFieldDefList { |
138 | pub(crate) syntax: SyntaxNode, | 83 | pub(crate) syntax: SyntaxNode, |
139 | } | 84 | } |
140 | impl AstNode for RecordFieldDefList { | ||
141 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_DEF_LIST } | ||
142 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
143 | if Self::can_cast(syntax.kind()) { | ||
144 | Some(Self { syntax }) | ||
145 | } else { | ||
146 | None | ||
147 | } | ||
148 | } | ||
149 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
150 | } | ||
151 | impl RecordFieldDefList { | 85 | impl RecordFieldDefList { |
152 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | 86 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } |
153 | pub fn fields(&self) -> AstChildren<RecordFieldDef> { support::children(&self.syntax) } | 87 | pub fn fields(&self) -> AstChildren<RecordFieldDef> { support::children(&self.syntax) } |
@@ -158,17 +92,6 @@ impl RecordFieldDefList { | |||
158 | pub struct RecordFieldDef { | 92 | pub struct RecordFieldDef { |
159 | pub(crate) syntax: SyntaxNode, | 93 | pub(crate) syntax: SyntaxNode, |
160 | } | 94 | } |
161 | impl AstNode for RecordFieldDef { | ||
162 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_DEF } | ||
163 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
164 | if Self::can_cast(syntax.kind()) { | ||
165 | Some(Self { syntax }) | ||
166 | } else { | ||
167 | None | ||
168 | } | ||
169 | } | ||
170 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
171 | } | ||
172 | impl ast::VisibilityOwner for RecordFieldDef {} | 95 | impl ast::VisibilityOwner for RecordFieldDef {} |
173 | impl ast::NameOwner for RecordFieldDef {} | 96 | impl ast::NameOwner for RecordFieldDef {} |
174 | impl ast::AttrsOwner for RecordFieldDef {} | 97 | impl ast::AttrsOwner for RecordFieldDef {} |
@@ -180,17 +103,6 @@ impl RecordFieldDef {} | |||
180 | pub struct TupleFieldDefList { | 103 | pub struct TupleFieldDefList { |
181 | pub(crate) syntax: SyntaxNode, | 104 | pub(crate) syntax: SyntaxNode, |
182 | } | 105 | } |
183 | impl AstNode for TupleFieldDefList { | ||
184 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_DEF_LIST } | ||
185 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
186 | if Self::can_cast(syntax.kind()) { | ||
187 | Some(Self { syntax }) | ||
188 | } else { | ||
189 | None | ||
190 | } | ||
191 | } | ||
192 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
193 | } | ||
194 | impl TupleFieldDefList { | 106 | impl TupleFieldDefList { |
195 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | 107 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } |
196 | pub fn fields(&self) -> AstChildren<TupleFieldDef> { support::children(&self.syntax) } | 108 | pub fn fields(&self) -> AstChildren<TupleFieldDef> { support::children(&self.syntax) } |
@@ -201,17 +113,6 @@ impl TupleFieldDefList { | |||
201 | pub struct TupleFieldDef { | 113 | pub struct TupleFieldDef { |
202 | pub(crate) syntax: SyntaxNode, | 114 | pub(crate) syntax: SyntaxNode, |
203 | } | 115 | } |
204 | impl AstNode for TupleFieldDef { | ||
205 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_DEF } | ||
206 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
207 | if Self::can_cast(syntax.kind()) { | ||
208 | Some(Self { syntax }) | ||
209 | } else { | ||
210 | None | ||
211 | } | ||
212 | } | ||
213 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
214 | } | ||
215 | impl ast::VisibilityOwner for TupleFieldDef {} | 116 | impl ast::VisibilityOwner for TupleFieldDef {} |
216 | impl ast::AttrsOwner for TupleFieldDef {} | 117 | impl ast::AttrsOwner for TupleFieldDef {} |
217 | impl TupleFieldDef { | 118 | impl TupleFieldDef { |
@@ -222,17 +123,6 @@ impl TupleFieldDef { | |||
222 | pub struct EnumDef { | 123 | pub struct EnumDef { |
223 | pub(crate) syntax: SyntaxNode, | 124 | pub(crate) syntax: SyntaxNode, |
224 | } | 125 | } |
225 | impl AstNode for EnumDef { | ||
226 | fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM_DEF } | ||
227 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
228 | if Self::can_cast(syntax.kind()) { | ||
229 | Some(Self { syntax }) | ||
230 | } else { | ||
231 | None | ||
232 | } | ||
233 | } | ||
234 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
235 | } | ||
236 | impl ast::VisibilityOwner for EnumDef {} | 126 | impl ast::VisibilityOwner for EnumDef {} |
237 | impl ast::NameOwner for EnumDef {} | 127 | impl ast::NameOwner for EnumDef {} |
238 | impl ast::TypeParamsOwner for EnumDef {} | 128 | impl ast::TypeParamsOwner for EnumDef {} |
@@ -247,17 +137,6 @@ impl EnumDef { | |||
247 | pub struct EnumVariantList { | 137 | pub struct EnumVariantList { |
248 | pub(crate) syntax: SyntaxNode, | 138 | pub(crate) syntax: SyntaxNode, |
249 | } | 139 | } |
250 | impl AstNode for EnumVariantList { | ||
251 | fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM_VARIANT_LIST } | ||
252 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
253 | if Self::can_cast(syntax.kind()) { | ||
254 | Some(Self { syntax }) | ||
255 | } else { | ||
256 | None | ||
257 | } | ||
258 | } | ||
259 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
260 | } | ||
261 | impl EnumVariantList { | 140 | impl EnumVariantList { |
262 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | 141 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } |
263 | pub fn variants(&self) -> AstChildren<EnumVariant> { support::children(&self.syntax) } | 142 | pub fn variants(&self) -> AstChildren<EnumVariant> { support::children(&self.syntax) } |
@@ -268,17 +147,6 @@ impl EnumVariantList { | |||
268 | pub struct EnumVariant { | 147 | pub struct EnumVariant { |
269 | pub(crate) syntax: SyntaxNode, | 148 | pub(crate) syntax: SyntaxNode, |
270 | } | 149 | } |
271 | impl AstNode for EnumVariant { | ||
272 | fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM_VARIANT } | ||
273 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
274 | if Self::can_cast(syntax.kind()) { | ||
275 | Some(Self { syntax }) | ||
276 | } else { | ||
277 | None | ||
278 | } | ||
279 | } | ||
280 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
281 | } | ||
282 | impl ast::VisibilityOwner for EnumVariant {} | 150 | impl ast::VisibilityOwner for EnumVariant {} |
283 | impl ast::NameOwner for EnumVariant {} | 151 | impl ast::NameOwner for EnumVariant {} |
284 | impl ast::DocCommentsOwner for EnumVariant {} | 152 | impl ast::DocCommentsOwner for EnumVariant {} |
@@ -293,17 +161,6 @@ impl EnumVariant { | |||
293 | pub struct TraitDef { | 161 | pub struct TraitDef { |
294 | pub(crate) syntax: SyntaxNode, | 162 | pub(crate) syntax: SyntaxNode, |
295 | } | 163 | } |
296 | impl AstNode for TraitDef { | ||
297 | fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT_DEF } | ||
298 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
299 | if Self::can_cast(syntax.kind()) { | ||
300 | Some(Self { syntax }) | ||
301 | } else { | ||
302 | None | ||
303 | } | ||
304 | } | ||
305 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
306 | } | ||
307 | impl ast::VisibilityOwner for TraitDef {} | 164 | impl ast::VisibilityOwner for TraitDef {} |
308 | impl ast::NameOwner for TraitDef {} | 165 | impl ast::NameOwner for TraitDef {} |
309 | impl ast::AttrsOwner for TraitDef {} | 166 | impl ast::AttrsOwner for TraitDef {} |
@@ -321,17 +178,6 @@ impl TraitDef { | |||
321 | pub struct Module { | 178 | pub struct Module { |
322 | pub(crate) syntax: SyntaxNode, | 179 | pub(crate) syntax: SyntaxNode, |
323 | } | 180 | } |
324 | impl AstNode for Module { | ||
325 | fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } | ||
326 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
327 | if Self::can_cast(syntax.kind()) { | ||
328 | Some(Self { syntax }) | ||
329 | } else { | ||
330 | None | ||
331 | } | ||
332 | } | ||
333 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
334 | } | ||
335 | impl ast::VisibilityOwner for Module {} | 181 | impl ast::VisibilityOwner for Module {} |
336 | impl ast::NameOwner for Module {} | 182 | impl ast::NameOwner for Module {} |
337 | impl ast::AttrsOwner for Module {} | 183 | impl ast::AttrsOwner for Module {} |
@@ -346,17 +192,6 @@ impl Module { | |||
346 | pub struct ItemList { | 192 | pub struct ItemList { |
347 | pub(crate) syntax: SyntaxNode, | 193 | pub(crate) syntax: SyntaxNode, |
348 | } | 194 | } |
349 | impl AstNode for ItemList { | ||
350 | fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST } | ||
351 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
352 | if Self::can_cast(syntax.kind()) { | ||
353 | Some(Self { syntax }) | ||
354 | } else { | ||
355 | None | ||
356 | } | ||
357 | } | ||
358 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
359 | } | ||
360 | impl ast::ModuleItemOwner for ItemList {} | 195 | impl ast::ModuleItemOwner for ItemList {} |
361 | impl ItemList { | 196 | impl ItemList { |
362 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | 197 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } |
@@ -368,17 +203,6 @@ impl ItemList { | |||
368 | pub struct ConstDef { | 203 | pub struct ConstDef { |
369 | pub(crate) syntax: SyntaxNode, | 204 | pub(crate) syntax: SyntaxNode, |
370 | } | 205 | } |
371 | impl AstNode for ConstDef { | ||
372 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_DEF } | ||
373 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
374 | if Self::can_cast(syntax.kind()) { | ||
375 | Some(Self { syntax }) | ||
376 | } else { | ||
377 | None | ||
378 | } | ||
379 | } | ||
380 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
381 | } | ||
382 | impl ast::VisibilityOwner for ConstDef {} | 206 | impl ast::VisibilityOwner for ConstDef {} |
383 | impl ast::NameOwner for ConstDef {} | 207 | impl ast::NameOwner for ConstDef {} |
384 | impl ast::TypeParamsOwner for ConstDef {} | 208 | impl ast::TypeParamsOwner for ConstDef {} |
@@ -397,17 +221,6 @@ impl ConstDef { | |||
397 | pub struct StaticDef { | 221 | pub struct StaticDef { |
398 | pub(crate) syntax: SyntaxNode, | 222 | pub(crate) syntax: SyntaxNode, |
399 | } | 223 | } |
400 | impl AstNode for StaticDef { | ||
401 | fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC_DEF } | ||
402 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
403 | if Self::can_cast(syntax.kind()) { | ||
404 | Some(Self { syntax }) | ||
405 | } else { | ||
406 | None | ||
407 | } | ||
408 | } | ||
409 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
410 | } | ||
411 | impl ast::VisibilityOwner for StaticDef {} | 224 | impl ast::VisibilityOwner for StaticDef {} |
412 | impl ast::NameOwner for StaticDef {} | 225 | impl ast::NameOwner for StaticDef {} |
413 | impl ast::TypeParamsOwner for StaticDef {} | 226 | impl ast::TypeParamsOwner for StaticDef {} |
@@ -426,17 +239,6 @@ impl StaticDef { | |||
426 | pub struct TypeAliasDef { | 239 | pub struct TypeAliasDef { |
427 | pub(crate) syntax: SyntaxNode, | 240 | pub(crate) syntax: SyntaxNode, |
428 | } | 241 | } |
429 | impl AstNode for TypeAliasDef { | ||
430 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS_DEF } | ||
431 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
432 | if Self::can_cast(syntax.kind()) { | ||
433 | Some(Self { syntax }) | ||
434 | } else { | ||
435 | None | ||
436 | } | ||
437 | } | ||
438 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
439 | } | ||
440 | impl ast::VisibilityOwner for TypeAliasDef {} | 242 | impl ast::VisibilityOwner for TypeAliasDef {} |
441 | impl ast::NameOwner for TypeAliasDef {} | 243 | impl ast::NameOwner for TypeAliasDef {} |
442 | impl ast::TypeParamsOwner for TypeAliasDef {} | 244 | impl ast::TypeParamsOwner for TypeAliasDef {} |
@@ -455,17 +257,6 @@ impl TypeAliasDef { | |||
455 | pub struct ImplDef { | 257 | pub struct ImplDef { |
456 | pub(crate) syntax: SyntaxNode, | 258 | pub(crate) syntax: SyntaxNode, |
457 | } | 259 | } |
458 | impl AstNode for ImplDef { | ||
459 | fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_DEF } | ||
460 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
461 | if Self::can_cast(syntax.kind()) { | ||
462 | Some(Self { syntax }) | ||
463 | } else { | ||
464 | None | ||
465 | } | ||
466 | } | ||
467 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
468 | } | ||
469 | impl ast::TypeParamsOwner for ImplDef {} | 260 | impl ast::TypeParamsOwner for ImplDef {} |
470 | impl ast::AttrsOwner for ImplDef {} | 261 | impl ast::AttrsOwner for ImplDef {} |
471 | impl ImplDef { | 262 | impl ImplDef { |
@@ -482,8 +273,1262 @@ impl ImplDef { | |||
482 | pub struct ParenType { | 273 | pub struct ParenType { |
483 | pub(crate) syntax: SyntaxNode, | 274 | pub(crate) syntax: SyntaxNode, |
484 | } | 275 | } |
485 | impl AstNode for ParenType { | 276 | impl ParenType { |
486 | fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE } | 277 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } |
278 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
279 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
280 | } | ||
281 | |||
282 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
283 | pub struct TupleType { | ||
284 | pub(crate) syntax: SyntaxNode, | ||
285 | } | ||
286 | impl TupleType { | ||
287 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
288 | pub fn fields(&self) -> AstChildren<TypeRef> { support::children(&self.syntax) } | ||
289 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
290 | } | ||
291 | |||
292 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
293 | pub struct NeverType { | ||
294 | pub(crate) syntax: SyntaxNode, | ||
295 | } | ||
296 | impl NeverType { | ||
297 | pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } | ||
298 | } | ||
299 | |||
300 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
301 | pub struct PathType { | ||
302 | pub(crate) syntax: SyntaxNode, | ||
303 | } | ||
304 | impl PathType { | ||
305 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
306 | } | ||
307 | |||
308 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
309 | pub struct PointerType { | ||
310 | pub(crate) syntax: SyntaxNode, | ||
311 | } | ||
312 | impl PointerType { | ||
313 | pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } | ||
314 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | ||
315 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
316 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
317 | } | ||
318 | |||
319 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
320 | pub struct ArrayType { | ||
321 | pub(crate) syntax: SyntaxNode, | ||
322 | } | ||
323 | impl ArrayType { | ||
324 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
325 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
326 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
327 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
328 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
329 | } | ||
330 | |||
331 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
332 | pub struct SliceType { | ||
333 | pub(crate) syntax: SyntaxNode, | ||
334 | } | ||
335 | impl SliceType { | ||
336 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
337 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
338 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
339 | } | ||
340 | |||
341 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
342 | pub struct ReferenceType { | ||
343 | pub(crate) syntax: SyntaxNode, | ||
344 | } | ||
345 | impl ReferenceType { | ||
346 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | ||
347 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
348 | support::token(&self.syntax, T![lifetime]) | ||
349 | } | ||
350 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
351 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
352 | } | ||
353 | |||
354 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
355 | pub struct PlaceholderType { | ||
356 | pub(crate) syntax: SyntaxNode, | ||
357 | } | ||
358 | impl PlaceholderType { | ||
359 | pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } | ||
360 | } | ||
361 | |||
362 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
363 | pub struct FnPointerType { | ||
364 | pub(crate) syntax: SyntaxNode, | ||
365 | } | ||
366 | impl FnPointerType { | ||
367 | pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } | ||
368 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | ||
369 | pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) } | ||
370 | pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } | ||
371 | pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } | ||
372 | } | ||
373 | |||
374 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
375 | pub struct ForType { | ||
376 | pub(crate) syntax: SyntaxNode, | ||
377 | } | ||
378 | impl ForType { | ||
379 | pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } | ||
380 | pub fn type_param_list(&self) -> Option<TypeParamList> { support::child(&self.syntax) } | ||
381 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
382 | } | ||
383 | |||
384 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
385 | pub struct ImplTraitType { | ||
386 | pub(crate) syntax: SyntaxNode, | ||
387 | } | ||
388 | impl ast::TypeBoundsOwner for ImplTraitType {} | ||
389 | impl ImplTraitType { | ||
390 | pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) } | ||
391 | } | ||
392 | |||
393 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
394 | pub struct DynTraitType { | ||
395 | pub(crate) syntax: SyntaxNode, | ||
396 | } | ||
397 | impl ast::TypeBoundsOwner for DynTraitType {} | ||
398 | impl DynTraitType { | ||
399 | pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) } | ||
400 | } | ||
401 | |||
402 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
403 | pub struct TupleExpr { | ||
404 | pub(crate) syntax: SyntaxNode, | ||
405 | } | ||
406 | impl ast::AttrsOwner for TupleExpr {} | ||
407 | impl TupleExpr { | ||
408 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
409 | pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) } | ||
410 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
411 | } | ||
412 | |||
413 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
414 | pub struct ArrayExpr { | ||
415 | pub(crate) syntax: SyntaxNode, | ||
416 | } | ||
417 | impl ast::AttrsOwner for ArrayExpr {} | ||
418 | impl ArrayExpr { | ||
419 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
420 | pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) } | ||
421 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
422 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
423 | } | ||
424 | |||
425 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
426 | pub struct ParenExpr { | ||
427 | pub(crate) syntax: SyntaxNode, | ||
428 | } | ||
429 | impl ast::AttrsOwner for ParenExpr {} | ||
430 | impl ParenExpr { | ||
431 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
432 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
433 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
434 | } | ||
435 | |||
436 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
437 | pub struct PathExpr { | ||
438 | pub(crate) syntax: SyntaxNode, | ||
439 | } | ||
440 | impl PathExpr { | ||
441 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
442 | } | ||
443 | |||
444 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
445 | pub struct LambdaExpr { | ||
446 | pub(crate) syntax: SyntaxNode, | ||
447 | } | ||
448 | impl ast::AttrsOwner for LambdaExpr {} | ||
449 | impl LambdaExpr { | ||
450 | pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) } | ||
451 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } | ||
452 | pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) } | ||
453 | pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } | ||
454 | pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } | ||
455 | pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
456 | } | ||
457 | |||
458 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
459 | pub struct IfExpr { | ||
460 | pub(crate) syntax: SyntaxNode, | ||
461 | } | ||
462 | impl ast::AttrsOwner for IfExpr {} | ||
463 | impl IfExpr { | ||
464 | pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } | ||
465 | pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } | ||
466 | } | ||
467 | |||
468 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
469 | pub struct LoopExpr { | ||
470 | pub(crate) syntax: SyntaxNode, | ||
471 | } | ||
472 | impl ast::AttrsOwner for LoopExpr {} | ||
473 | impl ast::LoopBodyOwner for LoopExpr {} | ||
474 | impl LoopExpr { | ||
475 | pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) } | ||
476 | } | ||
477 | |||
478 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
479 | pub struct TryBlockExpr { | ||
480 | pub(crate) syntax: SyntaxNode, | ||
481 | } | ||
482 | impl ast::AttrsOwner for TryBlockExpr {} | ||
483 | impl TryBlockExpr { | ||
484 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } | ||
485 | pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) } | ||
486 | } | ||
487 | |||
488 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
489 | pub struct ForExpr { | ||
490 | pub(crate) syntax: SyntaxNode, | ||
491 | } | ||
492 | impl ast::AttrsOwner for ForExpr {} | ||
493 | impl ast::LoopBodyOwner for ForExpr {} | ||
494 | impl ForExpr { | ||
495 | pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } | ||
496 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
497 | pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) } | ||
498 | pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
499 | } | ||
500 | |||
501 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
502 | pub struct WhileExpr { | ||
503 | pub(crate) syntax: SyntaxNode, | ||
504 | } | ||
505 | impl ast::AttrsOwner for WhileExpr {} | ||
506 | impl ast::LoopBodyOwner for WhileExpr {} | ||
507 | impl WhileExpr { | ||
508 | pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) } | ||
509 | pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } | ||
510 | } | ||
511 | |||
512 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
513 | pub struct ContinueExpr { | ||
514 | pub(crate) syntax: SyntaxNode, | ||
515 | } | ||
516 | impl ast::AttrsOwner for ContinueExpr {} | ||
517 | impl ContinueExpr { | ||
518 | pub fn continue_token(&self) -> Option<SyntaxToken> { | ||
519 | support::token(&self.syntax, T![continue]) | ||
520 | } | ||
521 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
522 | support::token(&self.syntax, T![lifetime]) | ||
523 | } | ||
524 | } | ||
525 | |||
526 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
527 | pub struct BreakExpr { | ||
528 | pub(crate) syntax: SyntaxNode, | ||
529 | } | ||
530 | impl ast::AttrsOwner for BreakExpr {} | ||
531 | impl BreakExpr { | ||
532 | pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) } | ||
533 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
534 | support::token(&self.syntax, T![lifetime]) | ||
535 | } | ||
536 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
537 | } | ||
538 | |||
539 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
540 | pub struct Label { | ||
541 | pub(crate) syntax: SyntaxNode, | ||
542 | } | ||
543 | impl Label { | ||
544 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
545 | support::token(&self.syntax, T![lifetime]) | ||
546 | } | ||
547 | } | ||
548 | |||
549 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
550 | pub struct BlockExpr { | ||
551 | pub(crate) syntax: SyntaxNode, | ||
552 | } | ||
553 | impl ast::AttrsOwner for BlockExpr {} | ||
554 | impl BlockExpr { | ||
555 | pub fn label(&self) -> Option<Label> { support::child(&self.syntax) } | ||
556 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | ||
557 | pub fn block(&self) -> Option<Block> { support::child(&self.syntax) } | ||
558 | } | ||
559 | |||
560 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
561 | pub struct ReturnExpr { | ||
562 | pub(crate) syntax: SyntaxNode, | ||
563 | } | ||
564 | impl ast::AttrsOwner for ReturnExpr {} | ||
565 | impl ReturnExpr { | ||
566 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
567 | } | ||
568 | |||
569 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
570 | pub struct CallExpr { | ||
571 | pub(crate) syntax: SyntaxNode, | ||
572 | } | ||
573 | impl ast::ArgListOwner for CallExpr {} | ||
574 | impl CallExpr { | ||
575 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
576 | } | ||
577 | |||
578 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
579 | pub struct MethodCallExpr { | ||
580 | pub(crate) syntax: SyntaxNode, | ||
581 | } | ||
582 | impl ast::AttrsOwner for MethodCallExpr {} | ||
583 | impl ast::ArgListOwner for MethodCallExpr {} | ||
584 | impl MethodCallExpr { | ||
585 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
586 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } | ||
587 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
588 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } | ||
589 | } | ||
590 | |||
591 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
592 | pub struct IndexExpr { | ||
593 | pub(crate) syntax: SyntaxNode, | ||
594 | } | ||
595 | impl ast::AttrsOwner for IndexExpr {} | ||
596 | impl IndexExpr { | ||
597 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
598 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
599 | } | ||
600 | |||
601 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
602 | pub struct FieldExpr { | ||
603 | pub(crate) syntax: SyntaxNode, | ||
604 | } | ||
605 | impl ast::AttrsOwner for FieldExpr {} | ||
606 | impl FieldExpr { | ||
607 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
608 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } | ||
609 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
610 | } | ||
611 | |||
612 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
613 | pub struct AwaitExpr { | ||
614 | pub(crate) syntax: SyntaxNode, | ||
615 | } | ||
616 | impl ast::AttrsOwner for AwaitExpr {} | ||
617 | impl AwaitExpr { | ||
618 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
619 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } | ||
620 | pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) } | ||
621 | } | ||
622 | |||
623 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
624 | pub struct TryExpr { | ||
625 | pub(crate) syntax: SyntaxNode, | ||
626 | } | ||
627 | impl ast::AttrsOwner for TryExpr {} | ||
628 | impl TryExpr { | ||
629 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } | ||
630 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
631 | } | ||
632 | |||
633 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
634 | pub struct CastExpr { | ||
635 | pub(crate) syntax: SyntaxNode, | ||
636 | } | ||
637 | impl ast::AttrsOwner for CastExpr {} | ||
638 | impl CastExpr { | ||
639 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
640 | pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } | ||
641 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
642 | } | ||
643 | |||
644 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
645 | pub struct RefExpr { | ||
646 | pub(crate) syntax: SyntaxNode, | ||
647 | } | ||
648 | impl ast::AttrsOwner for RefExpr {} | ||
649 | impl RefExpr { | ||
650 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | ||
651 | pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) } | ||
652 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
653 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
654 | } | ||
655 | |||
656 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
657 | pub struct PrefixExpr { | ||
658 | pub(crate) syntax: SyntaxNode, | ||
659 | } | ||
660 | impl ast::AttrsOwner for PrefixExpr {} | ||
661 | impl PrefixExpr { | ||
662 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
663 | } | ||
664 | |||
665 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
666 | pub struct BoxExpr { | ||
667 | pub(crate) syntax: SyntaxNode, | ||
668 | } | ||
669 | impl ast::AttrsOwner for BoxExpr {} | ||
670 | impl BoxExpr { | ||
671 | pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } | ||
672 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
673 | } | ||
674 | |||
675 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
676 | pub struct RangeExpr { | ||
677 | pub(crate) syntax: SyntaxNode, | ||
678 | } | ||
679 | impl ast::AttrsOwner for RangeExpr {} | ||
680 | impl RangeExpr {} | ||
681 | |||
682 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
683 | pub struct BinExpr { | ||
684 | pub(crate) syntax: SyntaxNode, | ||
685 | } | ||
686 | impl ast::AttrsOwner for BinExpr {} | ||
687 | impl BinExpr {} | ||
688 | |||
689 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
690 | pub struct Literal { | ||
691 | pub(crate) syntax: SyntaxNode, | ||
692 | } | ||
693 | impl Literal {} | ||
694 | |||
695 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
696 | pub struct MatchExpr { | ||
697 | pub(crate) syntax: SyntaxNode, | ||
698 | } | ||
699 | impl ast::AttrsOwner for MatchExpr {} | ||
700 | impl MatchExpr { | ||
701 | pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) } | ||
702 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
703 | pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) } | ||
704 | } | ||
705 | |||
706 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
707 | pub struct MatchArmList { | ||
708 | pub(crate) syntax: SyntaxNode, | ||
709 | } | ||
710 | impl ast::AttrsOwner for MatchArmList {} | ||
711 | impl MatchArmList { | ||
712 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
713 | pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) } | ||
714 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
715 | } | ||
716 | |||
717 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
718 | pub struct MatchArm { | ||
719 | pub(crate) syntax: SyntaxNode, | ||
720 | } | ||
721 | impl ast::AttrsOwner for MatchArm {} | ||
722 | impl MatchArm { | ||
723 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
724 | pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) } | ||
725 | pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) } | ||
726 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
727 | } | ||
728 | |||
729 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
730 | pub struct MatchGuard { | ||
731 | pub(crate) syntax: SyntaxNode, | ||
732 | } | ||
733 | impl MatchGuard { | ||
734 | pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } | ||
735 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
736 | } | ||
737 | |||
738 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
739 | pub struct RecordLit { | ||
740 | pub(crate) syntax: SyntaxNode, | ||
741 | } | ||
742 | impl RecordLit { | ||
743 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
744 | pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) } | ||
745 | } | ||
746 | |||
747 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
748 | pub struct RecordFieldList { | ||
749 | pub(crate) syntax: SyntaxNode, | ||
750 | } | ||
751 | impl RecordFieldList { | ||
752 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
753 | pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) } | ||
754 | pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } | ||
755 | pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
756 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
757 | } | ||
758 | |||
759 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
760 | pub struct RecordField { | ||
761 | pub(crate) syntax: SyntaxNode, | ||
762 | } | ||
763 | impl ast::AttrsOwner for RecordField {} | ||
764 | impl RecordField { | ||
765 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
766 | pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } | ||
767 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
768 | } | ||
769 | |||
770 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
771 | pub struct OrPat { | ||
772 | pub(crate) syntax: SyntaxNode, | ||
773 | } | ||
774 | impl OrPat { | ||
775 | pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
776 | } | ||
777 | |||
778 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
779 | pub struct ParenPat { | ||
780 | pub(crate) syntax: SyntaxNode, | ||
781 | } | ||
782 | impl ParenPat { | ||
783 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
784 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
785 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
786 | } | ||
787 | |||
788 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
789 | pub struct RefPat { | ||
790 | pub(crate) syntax: SyntaxNode, | ||
791 | } | ||
792 | impl RefPat { | ||
793 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | ||
794 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
795 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
796 | } | ||
797 | |||
798 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
799 | pub struct BoxPat { | ||
800 | pub(crate) syntax: SyntaxNode, | ||
801 | } | ||
802 | impl BoxPat { | ||
803 | pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } | ||
804 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
805 | } | ||
806 | |||
807 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
808 | pub struct BindPat { | ||
809 | pub(crate) syntax: SyntaxNode, | ||
810 | } | ||
811 | impl ast::AttrsOwner for BindPat {} | ||
812 | impl ast::NameOwner for BindPat {} | ||
813 | impl BindPat { | ||
814 | pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) } | ||
815 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
816 | pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) } | ||
817 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
818 | } | ||
819 | |||
820 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
821 | pub struct PlaceholderPat { | ||
822 | pub(crate) syntax: SyntaxNode, | ||
823 | } | ||
824 | impl PlaceholderPat { | ||
825 | pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } | ||
826 | } | ||
827 | |||
828 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
829 | pub struct DotDotPat { | ||
830 | pub(crate) syntax: SyntaxNode, | ||
831 | } | ||
832 | impl DotDotPat { | ||
833 | pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } | ||
834 | } | ||
835 | |||
836 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
837 | pub struct PathPat { | ||
838 | pub(crate) syntax: SyntaxNode, | ||
839 | } | ||
840 | impl PathPat { | ||
841 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
842 | } | ||
843 | |||
844 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
845 | pub struct SlicePat { | ||
846 | pub(crate) syntax: SyntaxNode, | ||
847 | } | ||
848 | impl SlicePat { | ||
849 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
850 | pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
851 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
852 | } | ||
853 | |||
854 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
855 | pub struct RangePat { | ||
856 | pub(crate) syntax: SyntaxNode, | ||
857 | } | ||
858 | impl RangePat {} | ||
859 | |||
860 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
861 | pub struct LiteralPat { | ||
862 | pub(crate) syntax: SyntaxNode, | ||
863 | } | ||
864 | impl LiteralPat { | ||
865 | pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } | ||
866 | } | ||
867 | |||
868 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
869 | pub struct MacroPat { | ||
870 | pub(crate) syntax: SyntaxNode, | ||
871 | } | ||
872 | impl MacroPat { | ||
873 | pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) } | ||
874 | } | ||
875 | |||
876 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
877 | pub struct RecordPat { | ||
878 | pub(crate) syntax: SyntaxNode, | ||
879 | } | ||
880 | impl RecordPat { | ||
881 | pub fn record_field_pat_list(&self) -> Option<RecordFieldPatList> { | ||
882 | support::child(&self.syntax) | ||
883 | } | ||
884 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
885 | } | ||
886 | |||
887 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
888 | pub struct RecordFieldPatList { | ||
889 | pub(crate) syntax: SyntaxNode, | ||
890 | } | ||
891 | impl RecordFieldPatList { | ||
892 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
893 | pub fn pats(&self) -> AstChildren<RecordInnerPat> { support::children(&self.syntax) } | ||
894 | pub fn record_field_pats(&self) -> AstChildren<RecordFieldPat> { | ||
895 | support::children(&self.syntax) | ||
896 | } | ||
897 | pub fn bind_pats(&self) -> AstChildren<BindPat> { support::children(&self.syntax) } | ||
898 | pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } | ||
899 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
900 | } | ||
901 | |||
902 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
903 | pub struct RecordFieldPat { | ||
904 | pub(crate) syntax: SyntaxNode, | ||
905 | } | ||
906 | impl ast::AttrsOwner for RecordFieldPat {} | ||
907 | impl RecordFieldPat { | ||
908 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
909 | pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } | ||
910 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
911 | } | ||
912 | |||
913 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
914 | pub struct TupleStructPat { | ||
915 | pub(crate) syntax: SyntaxNode, | ||
916 | } | ||
917 | impl TupleStructPat { | ||
918 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
919 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
920 | pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
921 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
922 | } | ||
923 | |||
924 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
925 | pub struct TuplePat { | ||
926 | pub(crate) syntax: SyntaxNode, | ||
927 | } | ||
928 | impl TuplePat { | ||
929 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
930 | pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
931 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
932 | } | ||
933 | |||
934 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
935 | pub struct Visibility { | ||
936 | pub(crate) syntax: SyntaxNode, | ||
937 | } | ||
938 | impl Visibility { | ||
939 | pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) } | ||
940 | pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) } | ||
941 | pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } | ||
942 | pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } | ||
943 | } | ||
944 | |||
945 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
946 | pub struct Name { | ||
947 | pub(crate) syntax: SyntaxNode, | ||
948 | } | ||
949 | impl Name { | ||
950 | pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) } | ||
951 | } | ||
952 | |||
953 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
954 | pub struct NameRef { | ||
955 | pub(crate) syntax: SyntaxNode, | ||
956 | } | ||
957 | impl NameRef {} | ||
958 | |||
959 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
960 | pub struct MacroCall { | ||
961 | pub(crate) syntax: SyntaxNode, | ||
962 | } | ||
963 | impl ast::NameOwner for MacroCall {} | ||
964 | impl ast::AttrsOwner for MacroCall {} | ||
965 | impl ast::DocCommentsOwner for MacroCall {} | ||
966 | impl MacroCall { | ||
967 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
968 | pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } | ||
969 | pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } | ||
970 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
971 | } | ||
972 | |||
973 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
974 | pub struct Attr { | ||
975 | pub(crate) syntax: SyntaxNode, | ||
976 | } | ||
977 | impl Attr { | ||
978 | pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) } | ||
979 | pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } | ||
980 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
981 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
982 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
983 | pub fn input(&self) -> Option<AttrInput> { support::child(&self.syntax) } | ||
984 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
985 | } | ||
986 | |||
987 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
988 | pub struct TokenTree { | ||
989 | pub(crate) syntax: SyntaxNode, | ||
990 | } | ||
991 | impl TokenTree {} | ||
992 | |||
993 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
994 | pub struct TypeParamList { | ||
995 | pub(crate) syntax: SyntaxNode, | ||
996 | } | ||
997 | impl TypeParamList { | ||
998 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | ||
999 | pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) } | ||
1000 | pub fn type_params(&self) -> AstChildren<TypeParam> { support::children(&self.syntax) } | ||
1001 | pub fn lifetime_params(&self) -> AstChildren<LifetimeParam> { support::children(&self.syntax) } | ||
1002 | pub fn const_params(&self) -> AstChildren<ConstParam> { support::children(&self.syntax) } | ||
1003 | pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } | ||
1004 | } | ||
1005 | |||
1006 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1007 | pub struct TypeParam { | ||
1008 | pub(crate) syntax: SyntaxNode, | ||
1009 | } | ||
1010 | impl ast::NameOwner for TypeParam {} | ||
1011 | impl ast::AttrsOwner for TypeParam {} | ||
1012 | impl ast::TypeBoundsOwner for TypeParam {} | ||
1013 | impl TypeParam { | ||
1014 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1015 | pub fn default_type(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
1016 | } | ||
1017 | |||
1018 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1019 | pub struct ConstParam { | ||
1020 | pub(crate) syntax: SyntaxNode, | ||
1021 | } | ||
1022 | impl ast::NameOwner for ConstParam {} | ||
1023 | impl ast::AttrsOwner for ConstParam {} | ||
1024 | impl ast::TypeAscriptionOwner for ConstParam {} | ||
1025 | impl ConstParam { | ||
1026 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1027 | pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1028 | } | ||
1029 | |||
1030 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1031 | pub struct LifetimeParam { | ||
1032 | pub(crate) syntax: SyntaxNode, | ||
1033 | } | ||
1034 | impl ast::AttrsOwner for LifetimeParam {} | ||
1035 | impl LifetimeParam { | ||
1036 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
1037 | support::token(&self.syntax, T![lifetime]) | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1042 | pub struct TypeBound { | ||
1043 | pub(crate) syntax: SyntaxNode, | ||
1044 | } | ||
1045 | impl TypeBound { | ||
1046 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
1047 | support::token(&self.syntax, T![lifetime]) | ||
1048 | } | ||
1049 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | ||
1050 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
1051 | } | ||
1052 | |||
1053 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1054 | pub struct TypeBoundList { | ||
1055 | pub(crate) syntax: SyntaxNode, | ||
1056 | } | ||
1057 | impl TypeBoundList { | ||
1058 | pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) } | ||
1059 | } | ||
1060 | |||
1061 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1062 | pub struct WherePred { | ||
1063 | pub(crate) syntax: SyntaxNode, | ||
1064 | } | ||
1065 | impl ast::TypeBoundsOwner for WherePred {} | ||
1066 | impl WherePred { | ||
1067 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
1068 | support::token(&self.syntax, T![lifetime]) | ||
1069 | } | ||
1070 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
1071 | } | ||
1072 | |||
1073 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1074 | pub struct WhereClause { | ||
1075 | pub(crate) syntax: SyntaxNode, | ||
1076 | } | ||
1077 | impl WhereClause { | ||
1078 | pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) } | ||
1079 | pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) } | ||
1080 | } | ||
1081 | |||
1082 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1083 | pub struct Abi { | ||
1084 | pub(crate) syntax: SyntaxNode, | ||
1085 | } | ||
1086 | impl Abi {} | ||
1087 | |||
1088 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1089 | pub struct ExprStmt { | ||
1090 | pub(crate) syntax: SyntaxNode, | ||
1091 | } | ||
1092 | impl ast::AttrsOwner for ExprStmt {} | ||
1093 | impl ExprStmt { | ||
1094 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1095 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
1096 | } | ||
1097 | |||
1098 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1099 | pub struct LetStmt { | ||
1100 | pub(crate) syntax: SyntaxNode, | ||
1101 | } | ||
1102 | impl ast::AttrsOwner for LetStmt {} | ||
1103 | impl ast::TypeAscriptionOwner for LetStmt {} | ||
1104 | impl LetStmt { | ||
1105 | pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) } | ||
1106 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1107 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1108 | pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1109 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
1110 | } | ||
1111 | |||
1112 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1113 | pub struct Condition { | ||
1114 | pub(crate) syntax: SyntaxNode, | ||
1115 | } | ||
1116 | impl Condition { | ||
1117 | pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) } | ||
1118 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1119 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1120 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1121 | } | ||
1122 | |||
1123 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1124 | pub struct Block { | ||
1125 | pub(crate) syntax: SyntaxNode, | ||
1126 | } | ||
1127 | impl ast::AttrsOwner for Block {} | ||
1128 | impl ast::ModuleItemOwner for Block {} | ||
1129 | impl Block { | ||
1130 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
1131 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } | ||
1132 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1133 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
1134 | } | ||
1135 | |||
1136 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1137 | pub struct ParamList { | ||
1138 | pub(crate) syntax: SyntaxNode, | ||
1139 | } | ||
1140 | impl ParamList { | ||
1141 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
1142 | pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) } | ||
1143 | pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) } | ||
1144 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
1145 | } | ||
1146 | |||
1147 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1148 | pub struct SelfParam { | ||
1149 | pub(crate) syntax: SyntaxNode, | ||
1150 | } | ||
1151 | impl ast::TypeAscriptionOwner for SelfParam {} | ||
1152 | impl ast::AttrsOwner for SelfParam {} | ||
1153 | impl SelfParam { | ||
1154 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | ||
1155 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
1156 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
1157 | support::token(&self.syntax, T![lifetime]) | ||
1158 | } | ||
1159 | pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } | ||
1160 | } | ||
1161 | |||
1162 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1163 | pub struct Param { | ||
1164 | pub(crate) syntax: SyntaxNode, | ||
1165 | } | ||
1166 | impl ast::TypeAscriptionOwner for Param {} | ||
1167 | impl ast::AttrsOwner for Param {} | ||
1168 | impl Param { | ||
1169 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1170 | pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) } | ||
1171 | } | ||
1172 | |||
1173 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1174 | pub struct UseItem { | ||
1175 | pub(crate) syntax: SyntaxNode, | ||
1176 | } | ||
1177 | impl ast::AttrsOwner for UseItem {} | ||
1178 | impl ast::VisibilityOwner for UseItem {} | ||
1179 | impl UseItem { | ||
1180 | pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) } | ||
1181 | pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) } | ||
1182 | } | ||
1183 | |||
1184 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1185 | pub struct UseTree { | ||
1186 | pub(crate) syntax: SyntaxNode, | ||
1187 | } | ||
1188 | impl UseTree { | ||
1189 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1190 | pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } | ||
1191 | pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) } | ||
1192 | pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) } | ||
1193 | } | ||
1194 | |||
1195 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1196 | pub struct Alias { | ||
1197 | pub(crate) syntax: SyntaxNode, | ||
1198 | } | ||
1199 | impl ast::NameOwner for Alias {} | ||
1200 | impl Alias { | ||
1201 | pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } | ||
1202 | } | ||
1203 | |||
1204 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1205 | pub struct UseTreeList { | ||
1206 | pub(crate) syntax: SyntaxNode, | ||
1207 | } | ||
1208 | impl UseTreeList { | ||
1209 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
1210 | pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) } | ||
1211 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
1212 | } | ||
1213 | |||
1214 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1215 | pub struct ExternCrateItem { | ||
1216 | pub(crate) syntax: SyntaxNode, | ||
1217 | } | ||
1218 | impl ast::AttrsOwner for ExternCrateItem {} | ||
1219 | impl ast::VisibilityOwner for ExternCrateItem {} | ||
1220 | impl ExternCrateItem { | ||
1221 | pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) } | ||
1222 | pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } | ||
1223 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
1224 | pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) } | ||
1225 | } | ||
1226 | |||
1227 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1228 | pub struct ArgList { | ||
1229 | pub(crate) syntax: SyntaxNode, | ||
1230 | } | ||
1231 | impl ArgList { | ||
1232 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
1233 | pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) } | ||
1234 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
1235 | } | ||
1236 | |||
1237 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1238 | pub struct Path { | ||
1239 | pub(crate) syntax: SyntaxNode, | ||
1240 | } | ||
1241 | impl Path { | ||
1242 | pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) } | ||
1243 | pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1244 | } | ||
1245 | |||
1246 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1247 | pub struct PathSegment { | ||
1248 | pub(crate) syntax: SyntaxNode, | ||
1249 | } | ||
1250 | impl PathSegment { | ||
1251 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } | ||
1252 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | ||
1253 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
1254 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } | ||
1255 | pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } | ||
1256 | pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } | ||
1257 | pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) } | ||
1258 | pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } | ||
1259 | } | ||
1260 | |||
1261 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1262 | pub struct TypeArgList { | ||
1263 | pub(crate) syntax: SyntaxNode, | ||
1264 | } | ||
1265 | impl TypeArgList { | ||
1266 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } | ||
1267 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | ||
1268 | pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) } | ||
1269 | pub fn type_args(&self) -> AstChildren<TypeArg> { support::children(&self.syntax) } | ||
1270 | pub fn lifetime_args(&self) -> AstChildren<LifetimeArg> { support::children(&self.syntax) } | ||
1271 | pub fn assoc_type_args(&self) -> AstChildren<AssocTypeArg> { support::children(&self.syntax) } | ||
1272 | pub fn const_args(&self) -> AstChildren<ConstArg> { support::children(&self.syntax) } | ||
1273 | pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } | ||
1274 | } | ||
1275 | |||
1276 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1277 | pub struct TypeArg { | ||
1278 | pub(crate) syntax: SyntaxNode, | ||
1279 | } | ||
1280 | impl TypeArg { | ||
1281 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
1282 | } | ||
1283 | |||
1284 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1285 | pub struct AssocTypeArg { | ||
1286 | pub(crate) syntax: SyntaxNode, | ||
1287 | } | ||
1288 | impl ast::TypeBoundsOwner for AssocTypeArg {} | ||
1289 | impl AssocTypeArg { | ||
1290 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
1291 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1292 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
1293 | } | ||
1294 | |||
1295 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1296 | pub struct LifetimeArg { | ||
1297 | pub(crate) syntax: SyntaxNode, | ||
1298 | } | ||
1299 | impl LifetimeArg { | ||
1300 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
1301 | support::token(&self.syntax, T![lifetime]) | ||
1302 | } | ||
1303 | } | ||
1304 | |||
1305 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1306 | pub struct ConstArg { | ||
1307 | pub(crate) syntax: SyntaxNode, | ||
1308 | } | ||
1309 | impl ConstArg { | ||
1310 | pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } | ||
1311 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1312 | pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } | ||
1313 | } | ||
1314 | |||
1315 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1316 | pub struct MacroItems { | ||
1317 | pub(crate) syntax: SyntaxNode, | ||
1318 | } | ||
1319 | impl ast::ModuleItemOwner for MacroItems {} | ||
1320 | impl MacroItems {} | ||
1321 | |||
1322 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1323 | pub struct MacroStmts { | ||
1324 | pub(crate) syntax: SyntaxNode, | ||
1325 | } | ||
1326 | impl MacroStmts { | ||
1327 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } | ||
1328 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1329 | } | ||
1330 | |||
1331 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1332 | pub struct ExternItemList { | ||
1333 | pub(crate) syntax: SyntaxNode, | ||
1334 | } | ||
1335 | impl ast::ModuleItemOwner for ExternItemList {} | ||
1336 | impl ExternItemList { | ||
1337 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
1338 | pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) } | ||
1339 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
1340 | } | ||
1341 | |||
1342 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1343 | pub struct ExternBlock { | ||
1344 | pub(crate) syntax: SyntaxNode, | ||
1345 | } | ||
1346 | impl ExternBlock { | ||
1347 | pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } | ||
1348 | pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) } | ||
1349 | } | ||
1350 | |||
1351 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1352 | pub struct MetaItem { | ||
1353 | pub(crate) syntax: SyntaxNode, | ||
1354 | } | ||
1355 | impl MetaItem { | ||
1356 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1357 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1358 | pub fn attr_input(&self) -> Option<AttrInput> { support::child(&self.syntax) } | ||
1359 | pub fn nested_meta_items(&self) -> AstChildren<MetaItem> { support::children(&self.syntax) } | ||
1360 | } | ||
1361 | |||
1362 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1363 | pub struct MacroDef { | ||
1364 | pub(crate) syntax: SyntaxNode, | ||
1365 | } | ||
1366 | impl MacroDef { | ||
1367 | pub fn name(&self) -> Option<Name> { support::child(&self.syntax) } | ||
1368 | pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } | ||
1369 | } | ||
1370 | |||
1371 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1372 | pub enum NominalDef { | ||
1373 | StructDef(StructDef), | ||
1374 | EnumDef(EnumDef), | ||
1375 | UnionDef(UnionDef), | ||
1376 | } | ||
1377 | impl ast::NameOwner for NominalDef {} | ||
1378 | impl ast::TypeParamsOwner for NominalDef {} | ||
1379 | impl ast::AttrsOwner for NominalDef {} | ||
1380 | |||
1381 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1382 | pub enum GenericParam { | ||
1383 | LifetimeParam(LifetimeParam), | ||
1384 | TypeParam(TypeParam), | ||
1385 | ConstParam(ConstParam), | ||
1386 | } | ||
1387 | |||
1388 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1389 | pub enum GenericArg { | ||
1390 | LifetimeArg(LifetimeArg), | ||
1391 | TypeArg(TypeArg), | ||
1392 | ConstArg(ConstArg), | ||
1393 | AssocTypeArg(AssocTypeArg), | ||
1394 | } | ||
1395 | |||
1396 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1397 | pub enum TypeRef { | ||
1398 | ParenType(ParenType), | ||
1399 | TupleType(TupleType), | ||
1400 | NeverType(NeverType), | ||
1401 | PathType(PathType), | ||
1402 | PointerType(PointerType), | ||
1403 | ArrayType(ArrayType), | ||
1404 | SliceType(SliceType), | ||
1405 | ReferenceType(ReferenceType), | ||
1406 | PlaceholderType(PlaceholderType), | ||
1407 | FnPointerType(FnPointerType), | ||
1408 | ForType(ForType), | ||
1409 | ImplTraitType(ImplTraitType), | ||
1410 | DynTraitType(DynTraitType), | ||
1411 | } | ||
1412 | |||
1413 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1414 | pub enum ModuleItem { | ||
1415 | StructDef(StructDef), | ||
1416 | UnionDef(UnionDef), | ||
1417 | EnumDef(EnumDef), | ||
1418 | FnDef(FnDef), | ||
1419 | TraitDef(TraitDef), | ||
1420 | TypeAliasDef(TypeAliasDef), | ||
1421 | ImplDef(ImplDef), | ||
1422 | UseItem(UseItem), | ||
1423 | ExternCrateItem(ExternCrateItem), | ||
1424 | ConstDef(ConstDef), | ||
1425 | StaticDef(StaticDef), | ||
1426 | Module(Module), | ||
1427 | MacroCall(MacroCall), | ||
1428 | ExternBlock(ExternBlock), | ||
1429 | } | ||
1430 | impl ast::NameOwner for ModuleItem {} | ||
1431 | impl ast::AttrsOwner for ModuleItem {} | ||
1432 | impl ast::VisibilityOwner for ModuleItem {} | ||
1433 | |||
1434 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1435 | pub enum ImplItem { | ||
1436 | FnDef(FnDef), | ||
1437 | TypeAliasDef(TypeAliasDef), | ||
1438 | ConstDef(ConstDef), | ||
1439 | } | ||
1440 | impl ast::NameOwner for ImplItem {} | ||
1441 | impl ast::AttrsOwner for ImplItem {} | ||
1442 | |||
1443 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1444 | pub enum ExternItem { | ||
1445 | FnDef(FnDef), | ||
1446 | StaticDef(StaticDef), | ||
1447 | } | ||
1448 | impl ast::NameOwner for ExternItem {} | ||
1449 | impl ast::AttrsOwner for ExternItem {} | ||
1450 | impl ast::VisibilityOwner for ExternItem {} | ||
1451 | |||
1452 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1453 | pub enum Expr { | ||
1454 | TupleExpr(TupleExpr), | ||
1455 | ArrayExpr(ArrayExpr), | ||
1456 | ParenExpr(ParenExpr), | ||
1457 | PathExpr(PathExpr), | ||
1458 | LambdaExpr(LambdaExpr), | ||
1459 | IfExpr(IfExpr), | ||
1460 | LoopExpr(LoopExpr), | ||
1461 | ForExpr(ForExpr), | ||
1462 | WhileExpr(WhileExpr), | ||
1463 | ContinueExpr(ContinueExpr), | ||
1464 | BreakExpr(BreakExpr), | ||
1465 | Label(Label), | ||
1466 | BlockExpr(BlockExpr), | ||
1467 | ReturnExpr(ReturnExpr), | ||
1468 | MatchExpr(MatchExpr), | ||
1469 | RecordLit(RecordLit), | ||
1470 | CallExpr(CallExpr), | ||
1471 | IndexExpr(IndexExpr), | ||
1472 | MethodCallExpr(MethodCallExpr), | ||
1473 | FieldExpr(FieldExpr), | ||
1474 | AwaitExpr(AwaitExpr), | ||
1475 | TryExpr(TryExpr), | ||
1476 | TryBlockExpr(TryBlockExpr), | ||
1477 | CastExpr(CastExpr), | ||
1478 | RefExpr(RefExpr), | ||
1479 | PrefixExpr(PrefixExpr), | ||
1480 | RangeExpr(RangeExpr), | ||
1481 | BinExpr(BinExpr), | ||
1482 | Literal(Literal), | ||
1483 | MacroCall(MacroCall), | ||
1484 | BoxExpr(BoxExpr), | ||
1485 | } | ||
1486 | impl ast::AttrsOwner for Expr {} | ||
1487 | |||
1488 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1489 | pub enum Pat { | ||
1490 | OrPat(OrPat), | ||
1491 | ParenPat(ParenPat), | ||
1492 | RefPat(RefPat), | ||
1493 | BoxPat(BoxPat), | ||
1494 | BindPat(BindPat), | ||
1495 | PlaceholderPat(PlaceholderPat), | ||
1496 | DotDotPat(DotDotPat), | ||
1497 | PathPat(PathPat), | ||
1498 | RecordPat(RecordPat), | ||
1499 | TupleStructPat(TupleStructPat), | ||
1500 | TuplePat(TuplePat), | ||
1501 | SlicePat(SlicePat), | ||
1502 | RangePat(RangePat), | ||
1503 | LiteralPat(LiteralPat), | ||
1504 | MacroPat(MacroPat), | ||
1505 | } | ||
1506 | |||
1507 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1508 | pub enum RecordInnerPat { | ||
1509 | RecordFieldPat(RecordFieldPat), | ||
1510 | BindPat(BindPat), | ||
1511 | } | ||
1512 | |||
1513 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1514 | pub enum AttrInput { | ||
1515 | Literal(Literal), | ||
1516 | TokenTree(TokenTree), | ||
1517 | } | ||
1518 | |||
1519 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1520 | pub enum Stmt { | ||
1521 | LetStmt(LetStmt), | ||
1522 | ExprStmt(ExprStmt), | ||
1523 | } | ||
1524 | |||
1525 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1526 | pub enum FieldDefList { | ||
1527 | RecordFieldDefList(RecordFieldDefList), | ||
1528 | TupleFieldDefList(TupleFieldDefList), | ||
1529 | } | ||
1530 | impl AstNode for SourceFile { | ||
1531 | fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE } | ||
487 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1532 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
488 | if Self::can_cast(syntax.kind()) { | 1533 | if Self::can_cast(syntax.kind()) { |
489 | Some(Self { syntax }) | 1534 | Some(Self { syntax }) |
@@ -493,18 +1538,30 @@ impl AstNode for ParenType { | |||
493 | } | 1538 | } |
494 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1539 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
495 | } | 1540 | } |
496 | impl ParenType { | 1541 | impl AstNode for FnDef { |
497 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | 1542 | fn can_cast(kind: SyntaxKind) -> bool { kind == FN_DEF } |
498 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | 1543 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
499 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | 1544 | if Self::can_cast(syntax.kind()) { |
1545 | Some(Self { syntax }) | ||
1546 | } else { | ||
1547 | None | ||
1548 | } | ||
1549 | } | ||
1550 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
500 | } | 1551 | } |
501 | 1552 | impl AstNode for RetType { | |
502 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1553 | fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE } |
503 | pub struct TupleType { | 1554 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
504 | pub(crate) syntax: SyntaxNode, | 1555 | if Self::can_cast(syntax.kind()) { |
1556 | Some(Self { syntax }) | ||
1557 | } else { | ||
1558 | None | ||
1559 | } | ||
1560 | } | ||
1561 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
505 | } | 1562 | } |
506 | impl AstNode for TupleType { | 1563 | impl AstNode for StructDef { |
507 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE } | 1564 | fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT_DEF } |
508 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1565 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
509 | if Self::can_cast(syntax.kind()) { | 1566 | if Self::can_cast(syntax.kind()) { |
510 | Some(Self { syntax }) | 1567 | Some(Self { syntax }) |
@@ -514,18 +1571,30 @@ impl AstNode for TupleType { | |||
514 | } | 1571 | } |
515 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1572 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
516 | } | 1573 | } |
517 | impl TupleType { | 1574 | impl AstNode for UnionDef { |
518 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | 1575 | fn can_cast(kind: SyntaxKind) -> bool { kind == UNION_DEF } |
519 | pub fn fields(&self) -> AstChildren<TypeRef> { support::children(&self.syntax) } | 1576 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
520 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | 1577 | if Self::can_cast(syntax.kind()) { |
1578 | Some(Self { syntax }) | ||
1579 | } else { | ||
1580 | None | ||
1581 | } | ||
1582 | } | ||
1583 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
521 | } | 1584 | } |
522 | 1585 | impl AstNode for RecordFieldDefList { | |
523 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1586 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_DEF_LIST } |
524 | pub struct NeverType { | 1587 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
525 | pub(crate) syntax: SyntaxNode, | 1588 | if Self::can_cast(syntax.kind()) { |
1589 | Some(Self { syntax }) | ||
1590 | } else { | ||
1591 | None | ||
1592 | } | ||
1593 | } | ||
1594 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
526 | } | 1595 | } |
527 | impl AstNode for NeverType { | 1596 | impl AstNode for RecordFieldDef { |
528 | fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE } | 1597 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_DEF } |
529 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1598 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
530 | if Self::can_cast(syntax.kind()) { | 1599 | if Self::can_cast(syntax.kind()) { |
531 | Some(Self { syntax }) | 1600 | Some(Self { syntax }) |
@@ -535,16 +1604,30 @@ impl AstNode for NeverType { | |||
535 | } | 1604 | } |
536 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1605 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
537 | } | 1606 | } |
538 | impl NeverType { | 1607 | impl AstNode for TupleFieldDefList { |
539 | pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } | 1608 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_DEF_LIST } |
1609 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
1610 | if Self::can_cast(syntax.kind()) { | ||
1611 | Some(Self { syntax }) | ||
1612 | } else { | ||
1613 | None | ||
1614 | } | ||
1615 | } | ||
1616 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
540 | } | 1617 | } |
541 | 1618 | impl AstNode for TupleFieldDef { | |
542 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1619 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_DEF } |
543 | pub struct PathType { | 1620 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
544 | pub(crate) syntax: SyntaxNode, | 1621 | if Self::can_cast(syntax.kind()) { |
1622 | Some(Self { syntax }) | ||
1623 | } else { | ||
1624 | None | ||
1625 | } | ||
1626 | } | ||
1627 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
545 | } | 1628 | } |
546 | impl AstNode for PathType { | 1629 | impl AstNode for EnumDef { |
547 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE } | 1630 | fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM_DEF } |
548 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1631 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
549 | if Self::can_cast(syntax.kind()) { | 1632 | if Self::can_cast(syntax.kind()) { |
550 | Some(Self { syntax }) | 1633 | Some(Self { syntax }) |
@@ -554,16 +1637,30 @@ impl AstNode for PathType { | |||
554 | } | 1637 | } |
555 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1638 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
556 | } | 1639 | } |
557 | impl PathType { | 1640 | impl AstNode for EnumVariantList { |
558 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | 1641 | fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM_VARIANT_LIST } |
1642 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
1643 | if Self::can_cast(syntax.kind()) { | ||
1644 | Some(Self { syntax }) | ||
1645 | } else { | ||
1646 | None | ||
1647 | } | ||
1648 | } | ||
1649 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
559 | } | 1650 | } |
560 | 1651 | impl AstNode for EnumVariant { | |
561 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1652 | fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM_VARIANT } |
562 | pub struct PointerType { | 1653 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
563 | pub(crate) syntax: SyntaxNode, | 1654 | if Self::can_cast(syntax.kind()) { |
1655 | Some(Self { syntax }) | ||
1656 | } else { | ||
1657 | None | ||
1658 | } | ||
1659 | } | ||
1660 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
564 | } | 1661 | } |
565 | impl AstNode for PointerType { | 1662 | impl AstNode for TraitDef { |
566 | fn can_cast(kind: SyntaxKind) -> bool { kind == POINTER_TYPE } | 1663 | fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT_DEF } |
567 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1664 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
568 | if Self::can_cast(syntax.kind()) { | 1665 | if Self::can_cast(syntax.kind()) { |
569 | Some(Self { syntax }) | 1666 | Some(Self { syntax }) |
@@ -573,19 +1670,30 @@ impl AstNode for PointerType { | |||
573 | } | 1670 | } |
574 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1671 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
575 | } | 1672 | } |
576 | impl PointerType { | 1673 | impl AstNode for Module { |
577 | pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } | 1674 | fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE } |
578 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | 1675 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
579 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | 1676 | if Self::can_cast(syntax.kind()) { |
580 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | 1677 | Some(Self { syntax }) |
1678 | } else { | ||
1679 | None | ||
1680 | } | ||
1681 | } | ||
1682 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
581 | } | 1683 | } |
582 | 1684 | impl AstNode for ItemList { | |
583 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1685 | fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST } |
584 | pub struct ArrayType { | 1686 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
585 | pub(crate) syntax: SyntaxNode, | 1687 | if Self::can_cast(syntax.kind()) { |
1688 | Some(Self { syntax }) | ||
1689 | } else { | ||
1690 | None | ||
1691 | } | ||
1692 | } | ||
1693 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
586 | } | 1694 | } |
587 | impl AstNode for ArrayType { | 1695 | impl AstNode for ConstDef { |
588 | fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE } | 1696 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_DEF } |
589 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1697 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
590 | if Self::can_cast(syntax.kind()) { | 1698 | if Self::can_cast(syntax.kind()) { |
591 | Some(Self { syntax }) | 1699 | Some(Self { syntax }) |
@@ -595,20 +1703,30 @@ impl AstNode for ArrayType { | |||
595 | } | 1703 | } |
596 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1704 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
597 | } | 1705 | } |
598 | impl ArrayType { | 1706 | impl AstNode for StaticDef { |
599 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | 1707 | fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC_DEF } |
600 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | 1708 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
601 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | 1709 | if Self::can_cast(syntax.kind()) { |
602 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | 1710 | Some(Self { syntax }) |
603 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | 1711 | } else { |
1712 | None | ||
1713 | } | ||
1714 | } | ||
1715 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
604 | } | 1716 | } |
605 | 1717 | impl AstNode for TypeAliasDef { | |
606 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1718 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS_DEF } |
607 | pub struct SliceType { | 1719 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
608 | pub(crate) syntax: SyntaxNode, | 1720 | if Self::can_cast(syntax.kind()) { |
1721 | Some(Self { syntax }) | ||
1722 | } else { | ||
1723 | None | ||
1724 | } | ||
1725 | } | ||
1726 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
609 | } | 1727 | } |
610 | impl AstNode for SliceType { | 1728 | impl AstNode for ImplDef { |
611 | fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE } | 1729 | fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_DEF } |
612 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1730 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
613 | if Self::can_cast(syntax.kind()) { | 1731 | if Self::can_cast(syntax.kind()) { |
614 | Some(Self { syntax }) | 1732 | Some(Self { syntax }) |
@@ -618,18 +1736,30 @@ impl AstNode for SliceType { | |||
618 | } | 1736 | } |
619 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1737 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
620 | } | 1738 | } |
621 | impl SliceType { | 1739 | impl AstNode for ParenType { |
622 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | 1740 | fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE } |
623 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | 1741 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
624 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | 1742 | if Self::can_cast(syntax.kind()) { |
1743 | Some(Self { syntax }) | ||
1744 | } else { | ||
1745 | None | ||
1746 | } | ||
1747 | } | ||
1748 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
625 | } | 1749 | } |
626 | 1750 | impl AstNode for TupleType { | |
627 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1751 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE } |
628 | pub struct ReferenceType { | 1752 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
629 | pub(crate) syntax: SyntaxNode, | 1753 | if Self::can_cast(syntax.kind()) { |
1754 | Some(Self { syntax }) | ||
1755 | } else { | ||
1756 | None | ||
1757 | } | ||
1758 | } | ||
1759 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
630 | } | 1760 | } |
631 | impl AstNode for ReferenceType { | 1761 | impl AstNode for NeverType { |
632 | fn can_cast(kind: SyntaxKind) -> bool { kind == REFERENCE_TYPE } | 1762 | fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE } |
633 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1763 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
634 | if Self::can_cast(syntax.kind()) { | 1764 | if Self::can_cast(syntax.kind()) { |
635 | Some(Self { syntax }) | 1765 | Some(Self { syntax }) |
@@ -639,21 +1769,30 @@ impl AstNode for ReferenceType { | |||
639 | } | 1769 | } |
640 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1770 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
641 | } | 1771 | } |
642 | impl ReferenceType { | 1772 | impl AstNode for PathType { |
643 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | 1773 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE } |
644 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | 1774 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
645 | support::token(&self.syntax, T![lifetime]) | 1775 | if Self::can_cast(syntax.kind()) { |
1776 | Some(Self { syntax }) | ||
1777 | } else { | ||
1778 | None | ||
1779 | } | ||
646 | } | 1780 | } |
647 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | 1781 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
648 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
649 | } | 1782 | } |
650 | 1783 | impl AstNode for PointerType { | |
651 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1784 | fn can_cast(kind: SyntaxKind) -> bool { kind == POINTER_TYPE } |
652 | pub struct PlaceholderType { | 1785 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
653 | pub(crate) syntax: SyntaxNode, | 1786 | if Self::can_cast(syntax.kind()) { |
1787 | Some(Self { syntax }) | ||
1788 | } else { | ||
1789 | None | ||
1790 | } | ||
1791 | } | ||
1792 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
654 | } | 1793 | } |
655 | impl AstNode for PlaceholderType { | 1794 | impl AstNode for ArrayType { |
656 | fn can_cast(kind: SyntaxKind) -> bool { kind == PLACEHOLDER_TYPE } | 1795 | fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE } |
657 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1796 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
658 | if Self::can_cast(syntax.kind()) { | 1797 | if Self::can_cast(syntax.kind()) { |
659 | Some(Self { syntax }) | 1798 | Some(Self { syntax }) |
@@ -663,13 +1802,38 @@ impl AstNode for PlaceholderType { | |||
663 | } | 1802 | } |
664 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1803 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
665 | } | 1804 | } |
666 | impl PlaceholderType { | 1805 | impl AstNode for SliceType { |
667 | pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } | 1806 | fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE } |
1807 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
1808 | if Self::can_cast(syntax.kind()) { | ||
1809 | Some(Self { syntax }) | ||
1810 | } else { | ||
1811 | None | ||
1812 | } | ||
1813 | } | ||
1814 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
668 | } | 1815 | } |
669 | 1816 | impl AstNode for ReferenceType { | |
670 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 1817 | fn can_cast(kind: SyntaxKind) -> bool { kind == REFERENCE_TYPE } |
671 | pub struct FnPointerType { | 1818 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
672 | pub(crate) syntax: SyntaxNode, | 1819 | if Self::can_cast(syntax.kind()) { |
1820 | Some(Self { syntax }) | ||
1821 | } else { | ||
1822 | None | ||
1823 | } | ||
1824 | } | ||
1825 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
1826 | } | ||
1827 | impl AstNode for PlaceholderType { | ||
1828 | fn can_cast(kind: SyntaxKind) -> bool { kind == PLACEHOLDER_TYPE } | ||
1829 | fn cast(syntax: SyntaxNode) -> Option<Self> { | ||
1830 | if Self::can_cast(syntax.kind()) { | ||
1831 | Some(Self { syntax }) | ||
1832 | } else { | ||
1833 | None | ||
1834 | } | ||
1835 | } | ||
1836 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | ||
673 | } | 1837 | } |
674 | impl AstNode for FnPointerType { | 1838 | impl AstNode for FnPointerType { |
675 | fn can_cast(kind: SyntaxKind) -> bool { kind == FN_POINTER_TYPE } | 1839 | fn can_cast(kind: SyntaxKind) -> bool { kind == FN_POINTER_TYPE } |
@@ -682,18 +1846,6 @@ impl AstNode for FnPointerType { | |||
682 | } | 1846 | } |
683 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1847 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
684 | } | 1848 | } |
685 | impl FnPointerType { | ||
686 | pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } | ||
687 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | ||
688 | pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) } | ||
689 | pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } | ||
690 | pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } | ||
691 | } | ||
692 | |||
693 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
694 | pub struct ForType { | ||
695 | pub(crate) syntax: SyntaxNode, | ||
696 | } | ||
697 | impl AstNode for ForType { | 1849 | impl AstNode for ForType { |
698 | fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE } | 1850 | fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE } |
699 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1851 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -705,16 +1857,6 @@ impl AstNode for ForType { | |||
705 | } | 1857 | } |
706 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1858 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
707 | } | 1859 | } |
708 | impl ForType { | ||
709 | pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } | ||
710 | pub fn type_param_list(&self) -> Option<TypeParamList> { support::child(&self.syntax) } | ||
711 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
712 | } | ||
713 | |||
714 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
715 | pub struct ImplTraitType { | ||
716 | pub(crate) syntax: SyntaxNode, | ||
717 | } | ||
718 | impl AstNode for ImplTraitType { | 1860 | impl AstNode for ImplTraitType { |
719 | fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE } | 1861 | fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE } |
720 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1862 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -726,15 +1868,6 @@ impl AstNode for ImplTraitType { | |||
726 | } | 1868 | } |
727 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1869 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
728 | } | 1870 | } |
729 | impl ast::TypeBoundsOwner for ImplTraitType {} | ||
730 | impl ImplTraitType { | ||
731 | pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) } | ||
732 | } | ||
733 | |||
734 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
735 | pub struct DynTraitType { | ||
736 | pub(crate) syntax: SyntaxNode, | ||
737 | } | ||
738 | impl AstNode for DynTraitType { | 1871 | impl AstNode for DynTraitType { |
739 | fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE } | 1872 | fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE } |
740 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1873 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -746,15 +1879,6 @@ impl AstNode for DynTraitType { | |||
746 | } | 1879 | } |
747 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1880 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
748 | } | 1881 | } |
749 | impl ast::TypeBoundsOwner for DynTraitType {} | ||
750 | impl DynTraitType { | ||
751 | pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) } | ||
752 | } | ||
753 | |||
754 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
755 | pub struct TupleExpr { | ||
756 | pub(crate) syntax: SyntaxNode, | ||
757 | } | ||
758 | impl AstNode for TupleExpr { | 1882 | impl AstNode for TupleExpr { |
759 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR } | 1883 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR } |
760 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1884 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -766,17 +1890,6 @@ impl AstNode for TupleExpr { | |||
766 | } | 1890 | } |
767 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1891 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
768 | } | 1892 | } |
769 | impl ast::AttrsOwner for TupleExpr {} | ||
770 | impl TupleExpr { | ||
771 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
772 | pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) } | ||
773 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
774 | } | ||
775 | |||
776 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
777 | pub struct ArrayExpr { | ||
778 | pub(crate) syntax: SyntaxNode, | ||
779 | } | ||
780 | impl AstNode for ArrayExpr { | 1893 | impl AstNode for ArrayExpr { |
781 | fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR } | 1894 | fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR } |
782 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1895 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -788,18 +1901,6 @@ impl AstNode for ArrayExpr { | |||
788 | } | 1901 | } |
789 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1902 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
790 | } | 1903 | } |
791 | impl ast::AttrsOwner for ArrayExpr {} | ||
792 | impl ArrayExpr { | ||
793 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
794 | pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) } | ||
795 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
796 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
797 | } | ||
798 | |||
799 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
800 | pub struct ParenExpr { | ||
801 | pub(crate) syntax: SyntaxNode, | ||
802 | } | ||
803 | impl AstNode for ParenExpr { | 1904 | impl AstNode for ParenExpr { |
804 | fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR } | 1905 | fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR } |
805 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1906 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -811,17 +1912,6 @@ impl AstNode for ParenExpr { | |||
811 | } | 1912 | } |
812 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1913 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
813 | } | 1914 | } |
814 | impl ast::AttrsOwner for ParenExpr {} | ||
815 | impl ParenExpr { | ||
816 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
817 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
818 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
819 | } | ||
820 | |||
821 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
822 | pub struct PathExpr { | ||
823 | pub(crate) syntax: SyntaxNode, | ||
824 | } | ||
825 | impl AstNode for PathExpr { | 1915 | impl AstNode for PathExpr { |
826 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR } | 1916 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR } |
827 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1917 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -833,14 +1923,6 @@ impl AstNode for PathExpr { | |||
833 | } | 1923 | } |
834 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1924 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
835 | } | 1925 | } |
836 | impl PathExpr { | ||
837 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
838 | } | ||
839 | |||
840 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
841 | pub struct LambdaExpr { | ||
842 | pub(crate) syntax: SyntaxNode, | ||
843 | } | ||
844 | impl AstNode for LambdaExpr { | 1926 | impl AstNode for LambdaExpr { |
845 | fn can_cast(kind: SyntaxKind) -> bool { kind == LAMBDA_EXPR } | 1927 | fn can_cast(kind: SyntaxKind) -> bool { kind == LAMBDA_EXPR } |
846 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1928 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -852,20 +1934,6 @@ impl AstNode for LambdaExpr { | |||
852 | } | 1934 | } |
853 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1935 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
854 | } | 1936 | } |
855 | impl ast::AttrsOwner for LambdaExpr {} | ||
856 | impl LambdaExpr { | ||
857 | pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) } | ||
858 | pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) } | ||
859 | pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) } | ||
860 | pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } | ||
861 | pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } | ||
862 | pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
863 | } | ||
864 | |||
865 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
866 | pub struct IfExpr { | ||
867 | pub(crate) syntax: SyntaxNode, | ||
868 | } | ||
869 | impl AstNode for IfExpr { | 1937 | impl AstNode for IfExpr { |
870 | fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR } | 1938 | fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR } |
871 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1939 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -877,16 +1945,6 @@ impl AstNode for IfExpr { | |||
877 | } | 1945 | } |
878 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1946 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
879 | } | 1947 | } |
880 | impl ast::AttrsOwner for IfExpr {} | ||
881 | impl IfExpr { | ||
882 | pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } | ||
883 | pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } | ||
884 | } | ||
885 | |||
886 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
887 | pub struct LoopExpr { | ||
888 | pub(crate) syntax: SyntaxNode, | ||
889 | } | ||
890 | impl AstNode for LoopExpr { | 1948 | impl AstNode for LoopExpr { |
891 | fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR } | 1949 | fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR } |
892 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1950 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -898,16 +1956,6 @@ impl AstNode for LoopExpr { | |||
898 | } | 1956 | } |
899 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1957 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
900 | } | 1958 | } |
901 | impl ast::AttrsOwner for LoopExpr {} | ||
902 | impl ast::LoopBodyOwner for LoopExpr {} | ||
903 | impl LoopExpr { | ||
904 | pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) } | ||
905 | } | ||
906 | |||
907 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
908 | pub struct TryBlockExpr { | ||
909 | pub(crate) syntax: SyntaxNode, | ||
910 | } | ||
911 | impl AstNode for TryBlockExpr { | 1959 | impl AstNode for TryBlockExpr { |
912 | fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_EXPR } | 1960 | fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_BLOCK_EXPR } |
913 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1961 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -919,16 +1967,6 @@ impl AstNode for TryBlockExpr { | |||
919 | } | 1967 | } |
920 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1968 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
921 | } | 1969 | } |
922 | impl ast::AttrsOwner for TryBlockExpr {} | ||
923 | impl TryBlockExpr { | ||
924 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } | ||
925 | pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) } | ||
926 | } | ||
927 | |||
928 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
929 | pub struct ForExpr { | ||
930 | pub(crate) syntax: SyntaxNode, | ||
931 | } | ||
932 | impl AstNode for ForExpr { | 1970 | impl AstNode for ForExpr { |
933 | fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR } | 1971 | fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR } |
934 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1972 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -940,19 +1978,6 @@ impl AstNode for ForExpr { | |||
940 | } | 1978 | } |
941 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1979 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
942 | } | 1980 | } |
943 | impl ast::AttrsOwner for ForExpr {} | ||
944 | impl ast::LoopBodyOwner for ForExpr {} | ||
945 | impl ForExpr { | ||
946 | pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) } | ||
947 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
948 | pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) } | ||
949 | pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
950 | } | ||
951 | |||
952 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
953 | pub struct WhileExpr { | ||
954 | pub(crate) syntax: SyntaxNode, | ||
955 | } | ||
956 | impl AstNode for WhileExpr { | 1981 | impl AstNode for WhileExpr { |
957 | fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR } | 1982 | fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR } |
958 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1983 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -964,17 +1989,6 @@ impl AstNode for WhileExpr { | |||
964 | } | 1989 | } |
965 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 1990 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
966 | } | 1991 | } |
967 | impl ast::AttrsOwner for WhileExpr {} | ||
968 | impl ast::LoopBodyOwner for WhileExpr {} | ||
969 | impl WhileExpr { | ||
970 | pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) } | ||
971 | pub fn condition(&self) -> Option<Condition> { support::child(&self.syntax) } | ||
972 | } | ||
973 | |||
974 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
975 | pub struct ContinueExpr { | ||
976 | pub(crate) syntax: SyntaxNode, | ||
977 | } | ||
978 | impl AstNode for ContinueExpr { | 1992 | impl AstNode for ContinueExpr { |
979 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR } | 1993 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR } |
980 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 1994 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -986,20 +2000,6 @@ impl AstNode for ContinueExpr { | |||
986 | } | 2000 | } |
987 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2001 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
988 | } | 2002 | } |
989 | impl ast::AttrsOwner for ContinueExpr {} | ||
990 | impl ContinueExpr { | ||
991 | pub fn continue_token(&self) -> Option<SyntaxToken> { | ||
992 | support::token(&self.syntax, T![continue]) | ||
993 | } | ||
994 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
995 | support::token(&self.syntax, T![lifetime]) | ||
996 | } | ||
997 | } | ||
998 | |||
999 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1000 | pub struct BreakExpr { | ||
1001 | pub(crate) syntax: SyntaxNode, | ||
1002 | } | ||
1003 | impl AstNode for BreakExpr { | 2003 | impl AstNode for BreakExpr { |
1004 | fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR } | 2004 | fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR } |
1005 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2005 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1011,19 +2011,6 @@ impl AstNode for BreakExpr { | |||
1011 | } | 2011 | } |
1012 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2012 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1013 | } | 2013 | } |
1014 | impl ast::AttrsOwner for BreakExpr {} | ||
1015 | impl BreakExpr { | ||
1016 | pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) } | ||
1017 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
1018 | support::token(&self.syntax, T![lifetime]) | ||
1019 | } | ||
1020 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1021 | } | ||
1022 | |||
1023 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1024 | pub struct Label { | ||
1025 | pub(crate) syntax: SyntaxNode, | ||
1026 | } | ||
1027 | impl AstNode for Label { | 2014 | impl AstNode for Label { |
1028 | fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL } | 2015 | fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL } |
1029 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2016 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1035,16 +2022,6 @@ impl AstNode for Label { | |||
1035 | } | 2022 | } |
1036 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2023 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1037 | } | 2024 | } |
1038 | impl Label { | ||
1039 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
1040 | support::token(&self.syntax, T![lifetime]) | ||
1041 | } | ||
1042 | } | ||
1043 | |||
1044 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1045 | pub struct BlockExpr { | ||
1046 | pub(crate) syntax: SyntaxNode, | ||
1047 | } | ||
1048 | impl AstNode for BlockExpr { | 2025 | impl AstNode for BlockExpr { |
1049 | fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR } | 2026 | fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR } |
1050 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2027 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1056,17 +2033,6 @@ impl AstNode for BlockExpr { | |||
1056 | } | 2033 | } |
1057 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2034 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1058 | } | 2035 | } |
1059 | impl ast::AttrsOwner for BlockExpr {} | ||
1060 | impl BlockExpr { | ||
1061 | pub fn label(&self) -> Option<Label> { support::child(&self.syntax) } | ||
1062 | pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) } | ||
1063 | pub fn block(&self) -> Option<Block> { support::child(&self.syntax) } | ||
1064 | } | ||
1065 | |||
1066 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1067 | pub struct ReturnExpr { | ||
1068 | pub(crate) syntax: SyntaxNode, | ||
1069 | } | ||
1070 | impl AstNode for ReturnExpr { | 2036 | impl AstNode for ReturnExpr { |
1071 | fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR } | 2037 | fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR } |
1072 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2038 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1078,15 +2044,6 @@ impl AstNode for ReturnExpr { | |||
1078 | } | 2044 | } |
1079 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2045 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1080 | } | 2046 | } |
1081 | impl ast::AttrsOwner for ReturnExpr {} | ||
1082 | impl ReturnExpr { | ||
1083 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1084 | } | ||
1085 | |||
1086 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1087 | pub struct CallExpr { | ||
1088 | pub(crate) syntax: SyntaxNode, | ||
1089 | } | ||
1090 | impl AstNode for CallExpr { | 2047 | impl AstNode for CallExpr { |
1091 | fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR } | 2048 | fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR } |
1092 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2049 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1098,15 +2055,6 @@ impl AstNode for CallExpr { | |||
1098 | } | 2055 | } |
1099 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2056 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1100 | } | 2057 | } |
1101 | impl ast::ArgListOwner for CallExpr {} | ||
1102 | impl CallExpr { | ||
1103 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1104 | } | ||
1105 | |||
1106 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1107 | pub struct MethodCallExpr { | ||
1108 | pub(crate) syntax: SyntaxNode, | ||
1109 | } | ||
1110 | impl AstNode for MethodCallExpr { | 2058 | impl AstNode for MethodCallExpr { |
1111 | fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR } | 2059 | fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR } |
1112 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2060 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1118,19 +2066,6 @@ impl AstNode for MethodCallExpr { | |||
1118 | } | 2066 | } |
1119 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2067 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1120 | } | 2068 | } |
1121 | impl ast::AttrsOwner for MethodCallExpr {} | ||
1122 | impl ast::ArgListOwner for MethodCallExpr {} | ||
1123 | impl MethodCallExpr { | ||
1124 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1125 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } | ||
1126 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
1127 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } | ||
1128 | } | ||
1129 | |||
1130 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1131 | pub struct IndexExpr { | ||
1132 | pub(crate) syntax: SyntaxNode, | ||
1133 | } | ||
1134 | impl AstNode for IndexExpr { | 2069 | impl AstNode for IndexExpr { |
1135 | fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR } | 2070 | fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR } |
1136 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2071 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1142,16 +2077,6 @@ impl AstNode for IndexExpr { | |||
1142 | } | 2077 | } |
1143 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2078 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1144 | } | 2079 | } |
1145 | impl ast::AttrsOwner for IndexExpr {} | ||
1146 | impl IndexExpr { | ||
1147 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
1148 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
1149 | } | ||
1150 | |||
1151 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1152 | pub struct FieldExpr { | ||
1153 | pub(crate) syntax: SyntaxNode, | ||
1154 | } | ||
1155 | impl AstNode for FieldExpr { | 2080 | impl AstNode for FieldExpr { |
1156 | fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR } | 2081 | fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR } |
1157 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2082 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1163,17 +2088,6 @@ impl AstNode for FieldExpr { | |||
1163 | } | 2088 | } |
1164 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2089 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1165 | } | 2090 | } |
1166 | impl ast::AttrsOwner for FieldExpr {} | ||
1167 | impl FieldExpr { | ||
1168 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1169 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } | ||
1170 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
1171 | } | ||
1172 | |||
1173 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1174 | pub struct AwaitExpr { | ||
1175 | pub(crate) syntax: SyntaxNode, | ||
1176 | } | ||
1177 | impl AstNode for AwaitExpr { | 2091 | impl AstNode for AwaitExpr { |
1178 | fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR } | 2092 | fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR } |
1179 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2093 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1185,17 +2099,6 @@ impl AstNode for AwaitExpr { | |||
1185 | } | 2099 | } |
1186 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2100 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1187 | } | 2101 | } |
1188 | impl ast::AttrsOwner for AwaitExpr {} | ||
1189 | impl AwaitExpr { | ||
1190 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1191 | pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) } | ||
1192 | pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) } | ||
1193 | } | ||
1194 | |||
1195 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1196 | pub struct TryExpr { | ||
1197 | pub(crate) syntax: SyntaxNode, | ||
1198 | } | ||
1199 | impl AstNode for TryExpr { | 2102 | impl AstNode for TryExpr { |
1200 | fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR } | 2103 | fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR } |
1201 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2104 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1207,16 +2110,6 @@ impl AstNode for TryExpr { | |||
1207 | } | 2110 | } |
1208 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2111 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1209 | } | 2112 | } |
1210 | impl ast::AttrsOwner for TryExpr {} | ||
1211 | impl TryExpr { | ||
1212 | pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) } | ||
1213 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1214 | } | ||
1215 | |||
1216 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1217 | pub struct CastExpr { | ||
1218 | pub(crate) syntax: SyntaxNode, | ||
1219 | } | ||
1220 | impl AstNode for CastExpr { | 2113 | impl AstNode for CastExpr { |
1221 | fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR } | 2114 | fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR } |
1222 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2115 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1228,17 +2121,6 @@ impl AstNode for CastExpr { | |||
1228 | } | 2121 | } |
1229 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2122 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1230 | } | 2123 | } |
1231 | impl ast::AttrsOwner for CastExpr {} | ||
1232 | impl CastExpr { | ||
1233 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1234 | pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } | ||
1235 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
1236 | } | ||
1237 | |||
1238 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1239 | pub struct RefExpr { | ||
1240 | pub(crate) syntax: SyntaxNode, | ||
1241 | } | ||
1242 | impl AstNode for RefExpr { | 2124 | impl AstNode for RefExpr { |
1243 | fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR } | 2125 | fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR } |
1244 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2126 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1250,18 +2132,6 @@ impl AstNode for RefExpr { | |||
1250 | } | 2132 | } |
1251 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2133 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1252 | } | 2134 | } |
1253 | impl ast::AttrsOwner for RefExpr {} | ||
1254 | impl RefExpr { | ||
1255 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | ||
1256 | pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) } | ||
1257 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
1258 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1259 | } | ||
1260 | |||
1261 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1262 | pub struct PrefixExpr { | ||
1263 | pub(crate) syntax: SyntaxNode, | ||
1264 | } | ||
1265 | impl AstNode for PrefixExpr { | 2135 | impl AstNode for PrefixExpr { |
1266 | fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR } | 2136 | fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR } |
1267 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2137 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1273,15 +2143,6 @@ impl AstNode for PrefixExpr { | |||
1273 | } | 2143 | } |
1274 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2144 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1275 | } | 2145 | } |
1276 | impl ast::AttrsOwner for PrefixExpr {} | ||
1277 | impl PrefixExpr { | ||
1278 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1279 | } | ||
1280 | |||
1281 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1282 | pub struct BoxExpr { | ||
1283 | pub(crate) syntax: SyntaxNode, | ||
1284 | } | ||
1285 | impl AstNode for BoxExpr { | 2146 | impl AstNode for BoxExpr { |
1286 | fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_EXPR } | 2147 | fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_EXPR } |
1287 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2148 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1293,16 +2154,6 @@ impl AstNode for BoxExpr { | |||
1293 | } | 2154 | } |
1294 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2155 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1295 | } | 2156 | } |
1296 | impl ast::AttrsOwner for BoxExpr {} | ||
1297 | impl BoxExpr { | ||
1298 | pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } | ||
1299 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1300 | } | ||
1301 | |||
1302 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1303 | pub struct RangeExpr { | ||
1304 | pub(crate) syntax: SyntaxNode, | ||
1305 | } | ||
1306 | impl AstNode for RangeExpr { | 2157 | impl AstNode for RangeExpr { |
1307 | fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_EXPR } | 2158 | fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_EXPR } |
1308 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2159 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1314,13 +2165,6 @@ impl AstNode for RangeExpr { | |||
1314 | } | 2165 | } |
1315 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2166 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1316 | } | 2167 | } |
1317 | impl ast::AttrsOwner for RangeExpr {} | ||
1318 | impl RangeExpr {} | ||
1319 | |||
1320 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1321 | pub struct BinExpr { | ||
1322 | pub(crate) syntax: SyntaxNode, | ||
1323 | } | ||
1324 | impl AstNode for BinExpr { | 2168 | impl AstNode for BinExpr { |
1325 | fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR } | 2169 | fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR } |
1326 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2170 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1332,13 +2176,6 @@ impl AstNode for BinExpr { | |||
1332 | } | 2176 | } |
1333 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2177 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1334 | } | 2178 | } |
1335 | impl ast::AttrsOwner for BinExpr {} | ||
1336 | impl BinExpr {} | ||
1337 | |||
1338 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1339 | pub struct Literal { | ||
1340 | pub(crate) syntax: SyntaxNode, | ||
1341 | } | ||
1342 | impl AstNode for Literal { | 2179 | impl AstNode for Literal { |
1343 | fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL } | 2180 | fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL } |
1344 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2181 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1350,12 +2187,6 @@ impl AstNode for Literal { | |||
1350 | } | 2187 | } |
1351 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2188 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1352 | } | 2189 | } |
1353 | impl Literal {} | ||
1354 | |||
1355 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1356 | pub struct MatchExpr { | ||
1357 | pub(crate) syntax: SyntaxNode, | ||
1358 | } | ||
1359 | impl AstNode for MatchExpr { | 2190 | impl AstNode for MatchExpr { |
1360 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR } | 2191 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR } |
1361 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2192 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1367,17 +2198,6 @@ impl AstNode for MatchExpr { | |||
1367 | } | 2198 | } |
1368 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2199 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1369 | } | 2200 | } |
1370 | impl ast::AttrsOwner for MatchExpr {} | ||
1371 | impl MatchExpr { | ||
1372 | pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) } | ||
1373 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1374 | pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) } | ||
1375 | } | ||
1376 | |||
1377 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1378 | pub struct MatchArmList { | ||
1379 | pub(crate) syntax: SyntaxNode, | ||
1380 | } | ||
1381 | impl AstNode for MatchArmList { | 2201 | impl AstNode for MatchArmList { |
1382 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST } | 2202 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST } |
1383 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2203 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1389,17 +2209,6 @@ impl AstNode for MatchArmList { | |||
1389 | } | 2209 | } |
1390 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2210 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1391 | } | 2211 | } |
1392 | impl ast::AttrsOwner for MatchArmList {} | ||
1393 | impl MatchArmList { | ||
1394 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
1395 | pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) } | ||
1396 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
1397 | } | ||
1398 | |||
1399 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1400 | pub struct MatchArm { | ||
1401 | pub(crate) syntax: SyntaxNode, | ||
1402 | } | ||
1403 | impl AstNode for MatchArm { | 2212 | impl AstNode for MatchArm { |
1404 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM } | 2213 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM } |
1405 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2214 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1411,18 +2220,6 @@ impl AstNode for MatchArm { | |||
1411 | } | 2220 | } |
1412 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2221 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1413 | } | 2222 | } |
1414 | impl ast::AttrsOwner for MatchArm {} | ||
1415 | impl MatchArm { | ||
1416 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1417 | pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) } | ||
1418 | pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) } | ||
1419 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1420 | } | ||
1421 | |||
1422 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1423 | pub struct MatchGuard { | ||
1424 | pub(crate) syntax: SyntaxNode, | ||
1425 | } | ||
1426 | impl AstNode for MatchGuard { | 2223 | impl AstNode for MatchGuard { |
1427 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD } | 2224 | fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD } |
1428 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2225 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1434,15 +2231,6 @@ impl AstNode for MatchGuard { | |||
1434 | } | 2231 | } |
1435 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2232 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1436 | } | 2233 | } |
1437 | impl MatchGuard { | ||
1438 | pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) } | ||
1439 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1440 | } | ||
1441 | |||
1442 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1443 | pub struct RecordLit { | ||
1444 | pub(crate) syntax: SyntaxNode, | ||
1445 | } | ||
1446 | impl AstNode for RecordLit { | 2234 | impl AstNode for RecordLit { |
1447 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_LIT } | 2235 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_LIT } |
1448 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2236 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1454,15 +2242,6 @@ impl AstNode for RecordLit { | |||
1454 | } | 2242 | } |
1455 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2243 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1456 | } | 2244 | } |
1457 | impl RecordLit { | ||
1458 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1459 | pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) } | ||
1460 | } | ||
1461 | |||
1462 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1463 | pub struct RecordFieldList { | ||
1464 | pub(crate) syntax: SyntaxNode, | ||
1465 | } | ||
1466 | impl AstNode for RecordFieldList { | 2245 | impl AstNode for RecordFieldList { |
1467 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST } | 2246 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST } |
1468 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2247 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1474,18 +2253,6 @@ impl AstNode for RecordFieldList { | |||
1474 | } | 2253 | } |
1475 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2254 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1476 | } | 2255 | } |
1477 | impl RecordFieldList { | ||
1478 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
1479 | pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) } | ||
1480 | pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } | ||
1481 | pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1482 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
1483 | } | ||
1484 | |||
1485 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1486 | pub struct RecordField { | ||
1487 | pub(crate) syntax: SyntaxNode, | ||
1488 | } | ||
1489 | impl AstNode for RecordField { | 2256 | impl AstNode for RecordField { |
1490 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD } | 2257 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD } |
1491 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2258 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1497,17 +2264,6 @@ impl AstNode for RecordField { | |||
1497 | } | 2264 | } |
1498 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2265 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1499 | } | 2266 | } |
1500 | impl ast::AttrsOwner for RecordField {} | ||
1501 | impl RecordField { | ||
1502 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
1503 | pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } | ||
1504 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
1505 | } | ||
1506 | |||
1507 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1508 | pub struct OrPat { | ||
1509 | pub(crate) syntax: SyntaxNode, | ||
1510 | } | ||
1511 | impl AstNode for OrPat { | 2267 | impl AstNode for OrPat { |
1512 | fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT } | 2268 | fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT } |
1513 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2269 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1519,14 +2275,6 @@ impl AstNode for OrPat { | |||
1519 | } | 2275 | } |
1520 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2276 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1521 | } | 2277 | } |
1522 | impl OrPat { | ||
1523 | pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
1524 | } | ||
1525 | |||
1526 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1527 | pub struct ParenPat { | ||
1528 | pub(crate) syntax: SyntaxNode, | ||
1529 | } | ||
1530 | impl AstNode for ParenPat { | 2278 | impl AstNode for ParenPat { |
1531 | fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT } | 2279 | fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT } |
1532 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2280 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1538,16 +2286,6 @@ impl AstNode for ParenPat { | |||
1538 | } | 2286 | } |
1539 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2287 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1540 | } | 2288 | } |
1541 | impl ParenPat { | ||
1542 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
1543 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1544 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
1545 | } | ||
1546 | |||
1547 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1548 | pub struct RefPat { | ||
1549 | pub(crate) syntax: SyntaxNode, | ||
1550 | } | ||
1551 | impl AstNode for RefPat { | 2289 | impl AstNode for RefPat { |
1552 | fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT } | 2290 | fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT } |
1553 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2291 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1559,16 +2297,6 @@ impl AstNode for RefPat { | |||
1559 | } | 2297 | } |
1560 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2298 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1561 | } | 2299 | } |
1562 | impl RefPat { | ||
1563 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | ||
1564 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
1565 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1566 | } | ||
1567 | |||
1568 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1569 | pub struct BoxPat { | ||
1570 | pub(crate) syntax: SyntaxNode, | ||
1571 | } | ||
1572 | impl AstNode for BoxPat { | 2300 | impl AstNode for BoxPat { |
1573 | fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT } | 2301 | fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT } |
1574 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2302 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1580,15 +2308,6 @@ impl AstNode for BoxPat { | |||
1580 | } | 2308 | } |
1581 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2309 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1582 | } | 2310 | } |
1583 | impl BoxPat { | ||
1584 | pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) } | ||
1585 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1586 | } | ||
1587 | |||
1588 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1589 | pub struct BindPat { | ||
1590 | pub(crate) syntax: SyntaxNode, | ||
1591 | } | ||
1592 | impl AstNode for BindPat { | 2311 | impl AstNode for BindPat { |
1593 | fn can_cast(kind: SyntaxKind) -> bool { kind == BIND_PAT } | 2312 | fn can_cast(kind: SyntaxKind) -> bool { kind == BIND_PAT } |
1594 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2313 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1600,19 +2319,6 @@ impl AstNode for BindPat { | |||
1600 | } | 2319 | } |
1601 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2320 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1602 | } | 2321 | } |
1603 | impl ast::AttrsOwner for BindPat {} | ||
1604 | impl ast::NameOwner for BindPat {} | ||
1605 | impl BindPat { | ||
1606 | pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) } | ||
1607 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
1608 | pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) } | ||
1609 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1610 | } | ||
1611 | |||
1612 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1613 | pub struct PlaceholderPat { | ||
1614 | pub(crate) syntax: SyntaxNode, | ||
1615 | } | ||
1616 | impl AstNode for PlaceholderPat { | 2322 | impl AstNode for PlaceholderPat { |
1617 | fn can_cast(kind: SyntaxKind) -> bool { kind == PLACEHOLDER_PAT } | 2323 | fn can_cast(kind: SyntaxKind) -> bool { kind == PLACEHOLDER_PAT } |
1618 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2324 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1624,14 +2330,6 @@ impl AstNode for PlaceholderPat { | |||
1624 | } | 2330 | } |
1625 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2331 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1626 | } | 2332 | } |
1627 | impl PlaceholderPat { | ||
1628 | pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) } | ||
1629 | } | ||
1630 | |||
1631 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1632 | pub struct DotDotPat { | ||
1633 | pub(crate) syntax: SyntaxNode, | ||
1634 | } | ||
1635 | impl AstNode for DotDotPat { | 2333 | impl AstNode for DotDotPat { |
1636 | fn can_cast(kind: SyntaxKind) -> bool { kind == DOT_DOT_PAT } | 2334 | fn can_cast(kind: SyntaxKind) -> bool { kind == DOT_DOT_PAT } |
1637 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2335 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1643,14 +2341,6 @@ impl AstNode for DotDotPat { | |||
1643 | } | 2341 | } |
1644 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2342 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1645 | } | 2343 | } |
1646 | impl DotDotPat { | ||
1647 | pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } | ||
1648 | } | ||
1649 | |||
1650 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1651 | pub struct PathPat { | ||
1652 | pub(crate) syntax: SyntaxNode, | ||
1653 | } | ||
1654 | impl AstNode for PathPat { | 2344 | impl AstNode for PathPat { |
1655 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT } | 2345 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT } |
1656 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2346 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1662,14 +2352,6 @@ impl AstNode for PathPat { | |||
1662 | } | 2352 | } |
1663 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2353 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1664 | } | 2354 | } |
1665 | impl PathPat { | ||
1666 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1667 | } | ||
1668 | |||
1669 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1670 | pub struct SlicePat { | ||
1671 | pub(crate) syntax: SyntaxNode, | ||
1672 | } | ||
1673 | impl AstNode for SlicePat { | 2355 | impl AstNode for SlicePat { |
1674 | fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT } | 2356 | fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT } |
1675 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2357 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1681,16 +2363,6 @@ impl AstNode for SlicePat { | |||
1681 | } | 2363 | } |
1682 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2364 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1683 | } | 2365 | } |
1684 | impl SlicePat { | ||
1685 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
1686 | pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
1687 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
1688 | } | ||
1689 | |||
1690 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1691 | pub struct RangePat { | ||
1692 | pub(crate) syntax: SyntaxNode, | ||
1693 | } | ||
1694 | impl AstNode for RangePat { | 2366 | impl AstNode for RangePat { |
1695 | fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT } | 2367 | fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT } |
1696 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2368 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1702,12 +2374,6 @@ impl AstNode for RangePat { | |||
1702 | } | 2374 | } |
1703 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2375 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1704 | } | 2376 | } |
1705 | impl RangePat {} | ||
1706 | |||
1707 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1708 | pub struct LiteralPat { | ||
1709 | pub(crate) syntax: SyntaxNode, | ||
1710 | } | ||
1711 | impl AstNode for LiteralPat { | 2377 | impl AstNode for LiteralPat { |
1712 | fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT } | 2378 | fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT } |
1713 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2379 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1719,14 +2385,6 @@ impl AstNode for LiteralPat { | |||
1719 | } | 2385 | } |
1720 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2386 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1721 | } | 2387 | } |
1722 | impl LiteralPat { | ||
1723 | pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } | ||
1724 | } | ||
1725 | |||
1726 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1727 | pub struct MacroPat { | ||
1728 | pub(crate) syntax: SyntaxNode, | ||
1729 | } | ||
1730 | impl AstNode for MacroPat { | 2388 | impl AstNode for MacroPat { |
1731 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT } | 2389 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT } |
1732 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2390 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1738,14 +2396,6 @@ impl AstNode for MacroPat { | |||
1738 | } | 2396 | } |
1739 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2397 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1740 | } | 2398 | } |
1741 | impl MacroPat { | ||
1742 | pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) } | ||
1743 | } | ||
1744 | |||
1745 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1746 | pub struct RecordPat { | ||
1747 | pub(crate) syntax: SyntaxNode, | ||
1748 | } | ||
1749 | impl AstNode for RecordPat { | 2399 | impl AstNode for RecordPat { |
1750 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT } | 2400 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT } |
1751 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2401 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1757,17 +2407,6 @@ impl AstNode for RecordPat { | |||
1757 | } | 2407 | } |
1758 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2408 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1759 | } | 2409 | } |
1760 | impl RecordPat { | ||
1761 | pub fn record_field_pat_list(&self) -> Option<RecordFieldPatList> { | ||
1762 | support::child(&self.syntax) | ||
1763 | } | ||
1764 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1765 | } | ||
1766 | |||
1767 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1768 | pub struct RecordFieldPatList { | ||
1769 | pub(crate) syntax: SyntaxNode, | ||
1770 | } | ||
1771 | impl AstNode for RecordFieldPatList { | 2410 | impl AstNode for RecordFieldPatList { |
1772 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_PAT_LIST } | 2411 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_PAT_LIST } |
1773 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2412 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1779,21 +2418,6 @@ impl AstNode for RecordFieldPatList { | |||
1779 | } | 2418 | } |
1780 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2419 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1781 | } | 2420 | } |
1782 | impl RecordFieldPatList { | ||
1783 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
1784 | pub fn pats(&self) -> AstChildren<RecordInnerPat> { support::children(&self.syntax) } | ||
1785 | pub fn record_field_pats(&self) -> AstChildren<RecordFieldPat> { | ||
1786 | support::children(&self.syntax) | ||
1787 | } | ||
1788 | pub fn bind_pats(&self) -> AstChildren<BindPat> { support::children(&self.syntax) } | ||
1789 | pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) } | ||
1790 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
1791 | } | ||
1792 | |||
1793 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1794 | pub struct RecordFieldPat { | ||
1795 | pub(crate) syntax: SyntaxNode, | ||
1796 | } | ||
1797 | impl AstNode for RecordFieldPat { | 2421 | impl AstNode for RecordFieldPat { |
1798 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_PAT } | 2422 | fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_PAT } |
1799 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2423 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1805,17 +2429,6 @@ impl AstNode for RecordFieldPat { | |||
1805 | } | 2429 | } |
1806 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2430 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1807 | } | 2431 | } |
1808 | impl ast::AttrsOwner for RecordFieldPat {} | ||
1809 | impl RecordFieldPat { | ||
1810 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
1811 | pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) } | ||
1812 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
1813 | } | ||
1814 | |||
1815 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1816 | pub struct TupleStructPat { | ||
1817 | pub(crate) syntax: SyntaxNode, | ||
1818 | } | ||
1819 | impl AstNode for TupleStructPat { | 2432 | impl AstNode for TupleStructPat { |
1820 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT } | 2433 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT } |
1821 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2434 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1827,17 +2440,6 @@ impl AstNode for TupleStructPat { | |||
1827 | } | 2440 | } |
1828 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2441 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1829 | } | 2442 | } |
1830 | impl TupleStructPat { | ||
1831 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1832 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
1833 | pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
1834 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
1835 | } | ||
1836 | |||
1837 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1838 | pub struct TuplePat { | ||
1839 | pub(crate) syntax: SyntaxNode, | ||
1840 | } | ||
1841 | impl AstNode for TuplePat { | 2443 | impl AstNode for TuplePat { |
1842 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT } | 2444 | fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT } |
1843 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2445 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1849,16 +2451,6 @@ impl AstNode for TuplePat { | |||
1849 | } | 2451 | } |
1850 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2452 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1851 | } | 2453 | } |
1852 | impl TuplePat { | ||
1853 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
1854 | pub fn args(&self) -> AstChildren<Pat> { support::children(&self.syntax) } | ||
1855 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
1856 | } | ||
1857 | |||
1858 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1859 | pub struct Visibility { | ||
1860 | pub(crate) syntax: SyntaxNode, | ||
1861 | } | ||
1862 | impl AstNode for Visibility { | 2454 | impl AstNode for Visibility { |
1863 | fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY } | 2455 | fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY } |
1864 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2456 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1870,17 +2462,6 @@ impl AstNode for Visibility { | |||
1870 | } | 2462 | } |
1871 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2463 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1872 | } | 2464 | } |
1873 | impl Visibility { | ||
1874 | pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) } | ||
1875 | pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) } | ||
1876 | pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } | ||
1877 | pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } | ||
1878 | } | ||
1879 | |||
1880 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1881 | pub struct Name { | ||
1882 | pub(crate) syntax: SyntaxNode, | ||
1883 | } | ||
1884 | impl AstNode for Name { | 2465 | impl AstNode for Name { |
1885 | fn can_cast(kind: SyntaxKind) -> bool { kind == NAME } | 2466 | fn can_cast(kind: SyntaxKind) -> bool { kind == NAME } |
1886 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2467 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1892,14 +2473,6 @@ impl AstNode for Name { | |||
1892 | } | 2473 | } |
1893 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2474 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1894 | } | 2475 | } |
1895 | impl Name { | ||
1896 | pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) } | ||
1897 | } | ||
1898 | |||
1899 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1900 | pub struct NameRef { | ||
1901 | pub(crate) syntax: SyntaxNode, | ||
1902 | } | ||
1903 | impl AstNode for NameRef { | 2476 | impl AstNode for NameRef { |
1904 | fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF } | 2477 | fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF } |
1905 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2478 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1911,12 +2484,6 @@ impl AstNode for NameRef { | |||
1911 | } | 2484 | } |
1912 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2485 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1913 | } | 2486 | } |
1914 | impl NameRef {} | ||
1915 | |||
1916 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1917 | pub struct MacroCall { | ||
1918 | pub(crate) syntax: SyntaxNode, | ||
1919 | } | ||
1920 | impl AstNode for MacroCall { | 2487 | impl AstNode for MacroCall { |
1921 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL } | 2488 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL } |
1922 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2489 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1928,20 +2495,6 @@ impl AstNode for MacroCall { | |||
1928 | } | 2495 | } |
1929 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2496 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1930 | } | 2497 | } |
1931 | impl ast::NameOwner for MacroCall {} | ||
1932 | impl ast::AttrsOwner for MacroCall {} | ||
1933 | impl ast::DocCommentsOwner for MacroCall {} | ||
1934 | impl MacroCall { | ||
1935 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1936 | pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } | ||
1937 | pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } | ||
1938 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
1939 | } | ||
1940 | |||
1941 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1942 | pub struct Attr { | ||
1943 | pub(crate) syntax: SyntaxNode, | ||
1944 | } | ||
1945 | impl AstNode for Attr { | 2498 | impl AstNode for Attr { |
1946 | fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR } | 2499 | fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR } |
1947 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2500 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1953,20 +2506,6 @@ impl AstNode for Attr { | |||
1953 | } | 2506 | } |
1954 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2507 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1955 | } | 2508 | } |
1956 | impl Attr { | ||
1957 | pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) } | ||
1958 | pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) } | ||
1959 | pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) } | ||
1960 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
1961 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
1962 | pub fn input(&self) -> Option<AttrInput> { support::child(&self.syntax) } | ||
1963 | pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) } | ||
1964 | } | ||
1965 | |||
1966 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1967 | pub struct TokenTree { | ||
1968 | pub(crate) syntax: SyntaxNode, | ||
1969 | } | ||
1970 | impl AstNode for TokenTree { | 2509 | impl AstNode for TokenTree { |
1971 | fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE } | 2510 | fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE } |
1972 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2511 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1978,12 +2517,6 @@ impl AstNode for TokenTree { | |||
1978 | } | 2517 | } |
1979 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2518 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1980 | } | 2519 | } |
1981 | impl TokenTree {} | ||
1982 | |||
1983 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
1984 | pub struct TypeParamList { | ||
1985 | pub(crate) syntax: SyntaxNode, | ||
1986 | } | ||
1987 | impl AstNode for TypeParamList { | 2520 | impl AstNode for TypeParamList { |
1988 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM_LIST } | 2521 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM_LIST } |
1989 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2522 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -1995,19 +2528,6 @@ impl AstNode for TypeParamList { | |||
1995 | } | 2528 | } |
1996 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2529 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
1997 | } | 2530 | } |
1998 | impl TypeParamList { | ||
1999 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | ||
2000 | pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) } | ||
2001 | pub fn type_params(&self) -> AstChildren<TypeParam> { support::children(&self.syntax) } | ||
2002 | pub fn lifetime_params(&self) -> AstChildren<LifetimeParam> { support::children(&self.syntax) } | ||
2003 | pub fn const_params(&self) -> AstChildren<ConstParam> { support::children(&self.syntax) } | ||
2004 | pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } | ||
2005 | } | ||
2006 | |||
2007 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2008 | pub struct TypeParam { | ||
2009 | pub(crate) syntax: SyntaxNode, | ||
2010 | } | ||
2011 | impl AstNode for TypeParam { | 2531 | impl AstNode for TypeParam { |
2012 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM } | 2532 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM } |
2013 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2533 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2019,18 +2539,6 @@ impl AstNode for TypeParam { | |||
2019 | } | 2539 | } |
2020 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2540 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2021 | } | 2541 | } |
2022 | impl ast::NameOwner for TypeParam {} | ||
2023 | impl ast::AttrsOwner for TypeParam {} | ||
2024 | impl ast::TypeBoundsOwner for TypeParam {} | ||
2025 | impl TypeParam { | ||
2026 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
2027 | pub fn default_type(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
2028 | } | ||
2029 | |||
2030 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2031 | pub struct ConstParam { | ||
2032 | pub(crate) syntax: SyntaxNode, | ||
2033 | } | ||
2034 | impl AstNode for ConstParam { | 2542 | impl AstNode for ConstParam { |
2035 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM } | 2543 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM } |
2036 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2544 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2042,18 +2550,6 @@ impl AstNode for ConstParam { | |||
2042 | } | 2550 | } |
2043 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2551 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2044 | } | 2552 | } |
2045 | impl ast::NameOwner for ConstParam {} | ||
2046 | impl ast::AttrsOwner for ConstParam {} | ||
2047 | impl ast::TypeAscriptionOwner for ConstParam {} | ||
2048 | impl ConstParam { | ||
2049 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
2050 | pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
2051 | } | ||
2052 | |||
2053 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2054 | pub struct LifetimeParam { | ||
2055 | pub(crate) syntax: SyntaxNode, | ||
2056 | } | ||
2057 | impl AstNode for LifetimeParam { | 2553 | impl AstNode for LifetimeParam { |
2058 | fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM } | 2554 | fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM } |
2059 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2555 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2065,17 +2561,6 @@ impl AstNode for LifetimeParam { | |||
2065 | } | 2561 | } |
2066 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2562 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2067 | } | 2563 | } |
2068 | impl ast::AttrsOwner for LifetimeParam {} | ||
2069 | impl LifetimeParam { | ||
2070 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
2071 | support::token(&self.syntax, T![lifetime]) | ||
2072 | } | ||
2073 | } | ||
2074 | |||
2075 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2076 | pub struct TypeBound { | ||
2077 | pub(crate) syntax: SyntaxNode, | ||
2078 | } | ||
2079 | impl AstNode for TypeBound { | 2564 | impl AstNode for TypeBound { |
2080 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND } | 2565 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND } |
2081 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2566 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2087,18 +2572,6 @@ impl AstNode for TypeBound { | |||
2087 | } | 2572 | } |
2088 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2573 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2089 | } | 2574 | } |
2090 | impl TypeBound { | ||
2091 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
2092 | support::token(&self.syntax, T![lifetime]) | ||
2093 | } | ||
2094 | pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) } | ||
2095 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
2096 | } | ||
2097 | |||
2098 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2099 | pub struct TypeBoundList { | ||
2100 | pub(crate) syntax: SyntaxNode, | ||
2101 | } | ||
2102 | impl AstNode for TypeBoundList { | 2575 | impl AstNode for TypeBoundList { |
2103 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST } | 2576 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST } |
2104 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2577 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2110,14 +2583,6 @@ impl AstNode for TypeBoundList { | |||
2110 | } | 2583 | } |
2111 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2584 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2112 | } | 2585 | } |
2113 | impl TypeBoundList { | ||
2114 | pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) } | ||
2115 | } | ||
2116 | |||
2117 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2118 | pub struct WherePred { | ||
2119 | pub(crate) syntax: SyntaxNode, | ||
2120 | } | ||
2121 | impl AstNode for WherePred { | 2586 | impl AstNode for WherePred { |
2122 | fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED } | 2587 | fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED } |
2123 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2588 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2129,18 +2594,6 @@ impl AstNode for WherePred { | |||
2129 | } | 2594 | } |
2130 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2595 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2131 | } | 2596 | } |
2132 | impl ast::TypeBoundsOwner for WherePred {} | ||
2133 | impl WherePred { | ||
2134 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
2135 | support::token(&self.syntax, T![lifetime]) | ||
2136 | } | ||
2137 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
2138 | } | ||
2139 | |||
2140 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2141 | pub struct WhereClause { | ||
2142 | pub(crate) syntax: SyntaxNode, | ||
2143 | } | ||
2144 | impl AstNode for WhereClause { | 2597 | impl AstNode for WhereClause { |
2145 | fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE } | 2598 | fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE } |
2146 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2599 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2152,15 +2605,6 @@ impl AstNode for WhereClause { | |||
2152 | } | 2605 | } |
2153 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2606 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2154 | } | 2607 | } |
2155 | impl WhereClause { | ||
2156 | pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) } | ||
2157 | pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) } | ||
2158 | } | ||
2159 | |||
2160 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2161 | pub struct Abi { | ||
2162 | pub(crate) syntax: SyntaxNode, | ||
2163 | } | ||
2164 | impl AstNode for Abi { | 2608 | impl AstNode for Abi { |
2165 | fn can_cast(kind: SyntaxKind) -> bool { kind == ABI } | 2609 | fn can_cast(kind: SyntaxKind) -> bool { kind == ABI } |
2166 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2610 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2172,12 +2616,6 @@ impl AstNode for Abi { | |||
2172 | } | 2616 | } |
2173 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2617 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2174 | } | 2618 | } |
2175 | impl Abi {} | ||
2176 | |||
2177 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2178 | pub struct ExprStmt { | ||
2179 | pub(crate) syntax: SyntaxNode, | ||
2180 | } | ||
2181 | impl AstNode for ExprStmt { | 2619 | impl AstNode for ExprStmt { |
2182 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT } | 2620 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT } |
2183 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2621 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2189,16 +2627,6 @@ impl AstNode for ExprStmt { | |||
2189 | } | 2627 | } |
2190 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2628 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2191 | } | 2629 | } |
2192 | impl ast::AttrsOwner for ExprStmt {} | ||
2193 | impl ExprStmt { | ||
2194 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
2195 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
2196 | } | ||
2197 | |||
2198 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2199 | pub struct LetStmt { | ||
2200 | pub(crate) syntax: SyntaxNode, | ||
2201 | } | ||
2202 | impl AstNode for LetStmt { | 2630 | impl AstNode for LetStmt { |
2203 | fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT } | 2631 | fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT } |
2204 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2632 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2210,20 +2638,6 @@ impl AstNode for LetStmt { | |||
2210 | } | 2638 | } |
2211 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2639 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2212 | } | 2640 | } |
2213 | impl ast::AttrsOwner for LetStmt {} | ||
2214 | impl ast::TypeAscriptionOwner for LetStmt {} | ||
2215 | impl LetStmt { | ||
2216 | pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) } | ||
2217 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
2218 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
2219 | pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
2220 | pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) } | ||
2221 | } | ||
2222 | |||
2223 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2224 | pub struct Condition { | ||
2225 | pub(crate) syntax: SyntaxNode, | ||
2226 | } | ||
2227 | impl AstNode for Condition { | 2641 | impl AstNode for Condition { |
2228 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONDITION } | 2642 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONDITION } |
2229 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2643 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2235,17 +2649,6 @@ impl AstNode for Condition { | |||
2235 | } | 2649 | } |
2236 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2650 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2237 | } | 2651 | } |
2238 | impl Condition { | ||
2239 | pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) } | ||
2240 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
2241 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
2242 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
2243 | } | ||
2244 | |||
2245 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2246 | pub struct Block { | ||
2247 | pub(crate) syntax: SyntaxNode, | ||
2248 | } | ||
2249 | impl AstNode for Block { | 2652 | impl AstNode for Block { |
2250 | fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK } | 2653 | fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK } |
2251 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2654 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2257,19 +2660,6 @@ impl AstNode for Block { | |||
2257 | } | 2660 | } |
2258 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2661 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2259 | } | 2662 | } |
2260 | impl ast::AttrsOwner for Block {} | ||
2261 | impl ast::ModuleItemOwner for Block {} | ||
2262 | impl Block { | ||
2263 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
2264 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } | ||
2265 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
2266 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
2267 | } | ||
2268 | |||
2269 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2270 | pub struct ParamList { | ||
2271 | pub(crate) syntax: SyntaxNode, | ||
2272 | } | ||
2273 | impl AstNode for ParamList { | 2663 | impl AstNode for ParamList { |
2274 | fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST } | 2664 | fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST } |
2275 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2665 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2281,17 +2671,6 @@ impl AstNode for ParamList { | |||
2281 | } | 2671 | } |
2282 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2672 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2283 | } | 2673 | } |
2284 | impl ParamList { | ||
2285 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
2286 | pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) } | ||
2287 | pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) } | ||
2288 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
2289 | } | ||
2290 | |||
2291 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2292 | pub struct SelfParam { | ||
2293 | pub(crate) syntax: SyntaxNode, | ||
2294 | } | ||
2295 | impl AstNode for SelfParam { | 2674 | impl AstNode for SelfParam { |
2296 | fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM } | 2675 | fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM } |
2297 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2676 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2303,21 +2682,6 @@ impl AstNode for SelfParam { | |||
2303 | } | 2682 | } |
2304 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2683 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2305 | } | 2684 | } |
2306 | impl ast::TypeAscriptionOwner for SelfParam {} | ||
2307 | impl ast::AttrsOwner for SelfParam {} | ||
2308 | impl SelfParam { | ||
2309 | pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) } | ||
2310 | pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) } | ||
2311 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
2312 | support::token(&self.syntax, T![lifetime]) | ||
2313 | } | ||
2314 | pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) } | ||
2315 | } | ||
2316 | |||
2317 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2318 | pub struct Param { | ||
2319 | pub(crate) syntax: SyntaxNode, | ||
2320 | } | ||
2321 | impl AstNode for Param { | 2685 | impl AstNode for Param { |
2322 | fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM } | 2686 | fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM } |
2323 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2687 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2329,17 +2693,6 @@ impl AstNode for Param { | |||
2329 | } | 2693 | } |
2330 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2694 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2331 | } | 2695 | } |
2332 | impl ast::TypeAscriptionOwner for Param {} | ||
2333 | impl ast::AttrsOwner for Param {} | ||
2334 | impl Param { | ||
2335 | pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) } | ||
2336 | pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) } | ||
2337 | } | ||
2338 | |||
2339 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2340 | pub struct UseItem { | ||
2341 | pub(crate) syntax: SyntaxNode, | ||
2342 | } | ||
2343 | impl AstNode for UseItem { | 2696 | impl AstNode for UseItem { |
2344 | fn can_cast(kind: SyntaxKind) -> bool { kind == USE_ITEM } | 2697 | fn can_cast(kind: SyntaxKind) -> bool { kind == USE_ITEM } |
2345 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2698 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2351,17 +2704,6 @@ impl AstNode for UseItem { | |||
2351 | } | 2704 | } |
2352 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2705 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2353 | } | 2706 | } |
2354 | impl ast::AttrsOwner for UseItem {} | ||
2355 | impl ast::VisibilityOwner for UseItem {} | ||
2356 | impl UseItem { | ||
2357 | pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) } | ||
2358 | pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) } | ||
2359 | } | ||
2360 | |||
2361 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2362 | pub struct UseTree { | ||
2363 | pub(crate) syntax: SyntaxNode, | ||
2364 | } | ||
2365 | impl AstNode for UseTree { | 2707 | impl AstNode for UseTree { |
2366 | fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE } | 2708 | fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE } |
2367 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2709 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2373,17 +2715,6 @@ impl AstNode for UseTree { | |||
2373 | } | 2715 | } |
2374 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2716 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2375 | } | 2717 | } |
2376 | impl UseTree { | ||
2377 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
2378 | pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) } | ||
2379 | pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) } | ||
2380 | pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) } | ||
2381 | } | ||
2382 | |||
2383 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2384 | pub struct Alias { | ||
2385 | pub(crate) syntax: SyntaxNode, | ||
2386 | } | ||
2387 | impl AstNode for Alias { | 2718 | impl AstNode for Alias { |
2388 | fn can_cast(kind: SyntaxKind) -> bool { kind == ALIAS } | 2719 | fn can_cast(kind: SyntaxKind) -> bool { kind == ALIAS } |
2389 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2720 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2395,15 +2726,6 @@ impl AstNode for Alias { | |||
2395 | } | 2726 | } |
2396 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2727 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2397 | } | 2728 | } |
2398 | impl ast::NameOwner for Alias {} | ||
2399 | impl Alias { | ||
2400 | pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) } | ||
2401 | } | ||
2402 | |||
2403 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2404 | pub struct UseTreeList { | ||
2405 | pub(crate) syntax: SyntaxNode, | ||
2406 | } | ||
2407 | impl AstNode for UseTreeList { | 2729 | impl AstNode for UseTreeList { |
2408 | fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST } | 2730 | fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST } |
2409 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2731 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2415,16 +2737,6 @@ impl AstNode for UseTreeList { | |||
2415 | } | 2737 | } |
2416 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2738 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2417 | } | 2739 | } |
2418 | impl UseTreeList { | ||
2419 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
2420 | pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) } | ||
2421 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
2422 | } | ||
2423 | |||
2424 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2425 | pub struct ExternCrateItem { | ||
2426 | pub(crate) syntax: SyntaxNode, | ||
2427 | } | ||
2428 | impl AstNode for ExternCrateItem { | 2740 | impl AstNode for ExternCrateItem { |
2429 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE_ITEM } | 2741 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE_ITEM } |
2430 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2742 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2436,19 +2748,6 @@ impl AstNode for ExternCrateItem { | |||
2436 | } | 2748 | } |
2437 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2749 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2438 | } | 2750 | } |
2439 | impl ast::AttrsOwner for ExternCrateItem {} | ||
2440 | impl ast::VisibilityOwner for ExternCrateItem {} | ||
2441 | impl ExternCrateItem { | ||
2442 | pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) } | ||
2443 | pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) } | ||
2444 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
2445 | pub fn alias(&self) -> Option<Alias> { support::child(&self.syntax) } | ||
2446 | } | ||
2447 | |||
2448 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2449 | pub struct ArgList { | ||
2450 | pub(crate) syntax: SyntaxNode, | ||
2451 | } | ||
2452 | impl AstNode for ArgList { | 2751 | impl AstNode for ArgList { |
2453 | fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST } | 2752 | fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST } |
2454 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2753 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2460,16 +2759,6 @@ impl AstNode for ArgList { | |||
2460 | } | 2759 | } |
2461 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2760 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2462 | } | 2761 | } |
2463 | impl ArgList { | ||
2464 | pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) } | ||
2465 | pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) } | ||
2466 | pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) } | ||
2467 | } | ||
2468 | |||
2469 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2470 | pub struct Path { | ||
2471 | pub(crate) syntax: SyntaxNode, | ||
2472 | } | ||
2473 | impl AstNode for Path { | 2762 | impl AstNode for Path { |
2474 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH } | 2763 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH } |
2475 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2764 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2481,15 +2770,6 @@ impl AstNode for Path { | |||
2481 | } | 2770 | } |
2482 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2771 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2483 | } | 2772 | } |
2484 | impl Path { | ||
2485 | pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) } | ||
2486 | pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) } | ||
2487 | } | ||
2488 | |||
2489 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2490 | pub struct PathSegment { | ||
2491 | pub(crate) syntax: SyntaxNode, | ||
2492 | } | ||
2493 | impl AstNode for PathSegment { | 2773 | impl AstNode for PathSegment { |
2494 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT } | 2774 | fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT } |
2495 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2775 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2501,21 +2781,6 @@ impl AstNode for PathSegment { | |||
2501 | } | 2781 | } |
2502 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2782 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2503 | } | 2783 | } |
2504 | impl PathSegment { | ||
2505 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } | ||
2506 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | ||
2507 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
2508 | pub fn type_arg_list(&self) -> Option<TypeArgList> { support::child(&self.syntax) } | ||
2509 | pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) } | ||
2510 | pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) } | ||
2511 | pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) } | ||
2512 | pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } | ||
2513 | } | ||
2514 | |||
2515 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2516 | pub struct TypeArgList { | ||
2517 | pub(crate) syntax: SyntaxNode, | ||
2518 | } | ||
2519 | impl AstNode for TypeArgList { | 2784 | impl AstNode for TypeArgList { |
2520 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG_LIST } | 2785 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG_LIST } |
2521 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2786 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2527,21 +2792,6 @@ impl AstNode for TypeArgList { | |||
2527 | } | 2792 | } |
2528 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2793 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2529 | } | 2794 | } |
2530 | impl TypeArgList { | ||
2531 | pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) } | ||
2532 | pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) } | ||
2533 | pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) } | ||
2534 | pub fn type_args(&self) -> AstChildren<TypeArg> { support::children(&self.syntax) } | ||
2535 | pub fn lifetime_args(&self) -> AstChildren<LifetimeArg> { support::children(&self.syntax) } | ||
2536 | pub fn assoc_type_args(&self) -> AstChildren<AssocTypeArg> { support::children(&self.syntax) } | ||
2537 | pub fn const_args(&self) -> AstChildren<ConstArg> { support::children(&self.syntax) } | ||
2538 | pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) } | ||
2539 | } | ||
2540 | |||
2541 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2542 | pub struct TypeArg { | ||
2543 | pub(crate) syntax: SyntaxNode, | ||
2544 | } | ||
2545 | impl AstNode for TypeArg { | 2795 | impl AstNode for TypeArg { |
2546 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG } | 2796 | fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG } |
2547 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2797 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2553,14 +2803,6 @@ impl AstNode for TypeArg { | |||
2553 | } | 2803 | } |
2554 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2804 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2555 | } | 2805 | } |
2556 | impl TypeArg { | ||
2557 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
2558 | } | ||
2559 | |||
2560 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2561 | pub struct AssocTypeArg { | ||
2562 | pub(crate) syntax: SyntaxNode, | ||
2563 | } | ||
2564 | impl AstNode for AssocTypeArg { | 2806 | impl AstNode for AssocTypeArg { |
2565 | fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG } | 2807 | fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG } |
2566 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2808 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2572,17 +2814,6 @@ impl AstNode for AssocTypeArg { | |||
2572 | } | 2814 | } |
2573 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2815 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2574 | } | 2816 | } |
2575 | impl ast::TypeBoundsOwner for AssocTypeArg {} | ||
2576 | impl AssocTypeArg { | ||
2577 | pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) } | ||
2578 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
2579 | pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) } | ||
2580 | } | ||
2581 | |||
2582 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2583 | pub struct LifetimeArg { | ||
2584 | pub(crate) syntax: SyntaxNode, | ||
2585 | } | ||
2586 | impl AstNode for LifetimeArg { | 2817 | impl AstNode for LifetimeArg { |
2587 | fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG } | 2818 | fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG } |
2588 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2819 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2594,16 +2825,6 @@ impl AstNode for LifetimeArg { | |||
2594 | } | 2825 | } |
2595 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2826 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2596 | } | 2827 | } |
2597 | impl LifetimeArg { | ||
2598 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
2599 | support::token(&self.syntax, T![lifetime]) | ||
2600 | } | ||
2601 | } | ||
2602 | |||
2603 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2604 | pub struct ConstArg { | ||
2605 | pub(crate) syntax: SyntaxNode, | ||
2606 | } | ||
2607 | impl AstNode for ConstArg { | 2828 | impl AstNode for ConstArg { |
2608 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG } | 2829 | fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG } |
2609 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2830 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2615,16 +2836,6 @@ impl AstNode for ConstArg { | |||
2615 | } | 2836 | } |
2616 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2837 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2617 | } | 2838 | } |
2618 | impl ConstArg { | ||
2619 | pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) } | ||
2620 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
2621 | pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) } | ||
2622 | } | ||
2623 | |||
2624 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2625 | pub struct MacroItems { | ||
2626 | pub(crate) syntax: SyntaxNode, | ||
2627 | } | ||
2628 | impl AstNode for MacroItems { | 2839 | impl AstNode for MacroItems { |
2629 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS } | 2840 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS } |
2630 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2841 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2636,13 +2847,6 @@ impl AstNode for MacroItems { | |||
2636 | } | 2847 | } |
2637 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2848 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2638 | } | 2849 | } |
2639 | impl ast::ModuleItemOwner for MacroItems {} | ||
2640 | impl MacroItems {} | ||
2641 | |||
2642 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2643 | pub struct MacroStmts { | ||
2644 | pub(crate) syntax: SyntaxNode, | ||
2645 | } | ||
2646 | impl AstNode for MacroStmts { | 2850 | impl AstNode for MacroStmts { |
2647 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS } | 2851 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS } |
2648 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2852 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2654,15 +2858,6 @@ impl AstNode for MacroStmts { | |||
2654 | } | 2858 | } |
2655 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2859 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2656 | } | 2860 | } |
2657 | impl MacroStmts { | ||
2658 | pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) } | ||
2659 | pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } | ||
2660 | } | ||
2661 | |||
2662 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2663 | pub struct ExternItemList { | ||
2664 | pub(crate) syntax: SyntaxNode, | ||
2665 | } | ||
2666 | impl AstNode for ExternItemList { | 2861 | impl AstNode for ExternItemList { |
2667 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST } | 2862 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST } |
2668 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2863 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2674,17 +2869,6 @@ impl AstNode for ExternItemList { | |||
2674 | } | 2869 | } |
2675 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2870 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2676 | } | 2871 | } |
2677 | impl ast::ModuleItemOwner for ExternItemList {} | ||
2678 | impl ExternItemList { | ||
2679 | pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) } | ||
2680 | pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) } | ||
2681 | pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) } | ||
2682 | } | ||
2683 | |||
2684 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2685 | pub struct ExternBlock { | ||
2686 | pub(crate) syntax: SyntaxNode, | ||
2687 | } | ||
2688 | impl AstNode for ExternBlock { | 2872 | impl AstNode for ExternBlock { |
2689 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK } | 2873 | fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK } |
2690 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2874 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2696,15 +2880,6 @@ impl AstNode for ExternBlock { | |||
2696 | } | 2880 | } |
2697 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2881 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2698 | } | 2882 | } |
2699 | impl ExternBlock { | ||
2700 | pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) } | ||
2701 | pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) } | ||
2702 | } | ||
2703 | |||
2704 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2705 | pub struct MetaItem { | ||
2706 | pub(crate) syntax: SyntaxNode, | ||
2707 | } | ||
2708 | impl AstNode for MetaItem { | 2883 | impl AstNode for MetaItem { |
2709 | fn can_cast(kind: SyntaxKind) -> bool { kind == META_ITEM } | 2884 | fn can_cast(kind: SyntaxKind) -> bool { kind == META_ITEM } |
2710 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2885 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2716,17 +2891,6 @@ impl AstNode for MetaItem { | |||
2716 | } | 2891 | } |
2717 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2892 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2718 | } | 2893 | } |
2719 | impl MetaItem { | ||
2720 | pub fn path(&self) -> Option<Path> { support::child(&self.syntax) } | ||
2721 | pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) } | ||
2722 | pub fn attr_input(&self) -> Option<AttrInput> { support::child(&self.syntax) } | ||
2723 | pub fn nested_meta_items(&self) -> AstChildren<MetaItem> { support::children(&self.syntax) } | ||
2724 | } | ||
2725 | |||
2726 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2727 | pub struct MacroDef { | ||
2728 | pub(crate) syntax: SyntaxNode, | ||
2729 | } | ||
2730 | impl AstNode for MacroDef { | 2894 | impl AstNode for MacroDef { |
2731 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF } | 2895 | fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF } |
2732 | fn cast(syntax: SyntaxNode) -> Option<Self> { | 2896 | fn cast(syntax: SyntaxNode) -> Option<Self> { |
@@ -2738,17 +2902,6 @@ impl AstNode for MacroDef { | |||
2738 | } | 2902 | } |
2739 | fn syntax(&self) -> &SyntaxNode { &self.syntax } | 2903 | fn syntax(&self) -> &SyntaxNode { &self.syntax } |
2740 | } | 2904 | } |
2741 | impl MacroDef { | ||
2742 | pub fn name(&self) -> Option<Name> { support::child(&self.syntax) } | ||
2743 | pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) } | ||
2744 | } | ||
2745 | |||
2746 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2747 | pub enum NominalDef { | ||
2748 | StructDef(StructDef), | ||
2749 | EnumDef(EnumDef), | ||
2750 | UnionDef(UnionDef), | ||
2751 | } | ||
2752 | impl From<StructDef> for NominalDef { | 2905 | impl From<StructDef> for NominalDef { |
2753 | fn from(node: StructDef) -> NominalDef { NominalDef::StructDef(node) } | 2906 | fn from(node: StructDef) -> NominalDef { NominalDef::StructDef(node) } |
2754 | } | 2907 | } |
@@ -2782,16 +2935,6 @@ impl AstNode for NominalDef { | |||
2782 | } | 2935 | } |
2783 | } | 2936 | } |
2784 | } | 2937 | } |
2785 | impl ast::NameOwner for NominalDef {} | ||
2786 | impl ast::TypeParamsOwner for NominalDef {} | ||
2787 | impl ast::AttrsOwner for NominalDef {} | ||
2788 | |||
2789 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2790 | pub enum GenericParam { | ||
2791 | LifetimeParam(LifetimeParam), | ||
2792 | TypeParam(TypeParam), | ||
2793 | ConstParam(ConstParam), | ||
2794 | } | ||
2795 | impl From<LifetimeParam> for GenericParam { | 2938 | impl From<LifetimeParam> for GenericParam { |
2796 | fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) } | 2939 | fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) } |
2797 | } | 2940 | } |
@@ -2825,14 +2968,6 @@ impl AstNode for GenericParam { | |||
2825 | } | 2968 | } |
2826 | } | 2969 | } |
2827 | } | 2970 | } |
2828 | |||
2829 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2830 | pub enum GenericArg { | ||
2831 | LifetimeArg(LifetimeArg), | ||
2832 | TypeArg(TypeArg), | ||
2833 | ConstArg(ConstArg), | ||
2834 | AssocTypeArg(AssocTypeArg), | ||
2835 | } | ||
2836 | impl From<LifetimeArg> for GenericArg { | 2971 | impl From<LifetimeArg> for GenericArg { |
2837 | fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) } | 2972 | fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) } |
2838 | } | 2973 | } |
@@ -2871,23 +3006,6 @@ impl AstNode for GenericArg { | |||
2871 | } | 3006 | } |
2872 | } | 3007 | } |
2873 | } | 3008 | } |
2874 | |||
2875 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2876 | pub enum TypeRef { | ||
2877 | ParenType(ParenType), | ||
2878 | TupleType(TupleType), | ||
2879 | NeverType(NeverType), | ||
2880 | PathType(PathType), | ||
2881 | PointerType(PointerType), | ||
2882 | ArrayType(ArrayType), | ||
2883 | SliceType(SliceType), | ||
2884 | ReferenceType(ReferenceType), | ||
2885 | PlaceholderType(PlaceholderType), | ||
2886 | FnPointerType(FnPointerType), | ||
2887 | ForType(ForType), | ||
2888 | ImplTraitType(ImplTraitType), | ||
2889 | DynTraitType(DynTraitType), | ||
2890 | } | ||
2891 | impl From<ParenType> for TypeRef { | 3009 | impl From<ParenType> for TypeRef { |
2892 | fn from(node: ParenType) -> TypeRef { TypeRef::ParenType(node) } | 3010 | fn from(node: ParenType) -> TypeRef { TypeRef::ParenType(node) } |
2893 | } | 3011 | } |
@@ -2973,24 +3091,6 @@ impl AstNode for TypeRef { | |||
2973 | } | 3091 | } |
2974 | } | 3092 | } |
2975 | } | 3093 | } |
2976 | |||
2977 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
2978 | pub enum ModuleItem { | ||
2979 | StructDef(StructDef), | ||
2980 | UnionDef(UnionDef), | ||
2981 | EnumDef(EnumDef), | ||
2982 | FnDef(FnDef), | ||
2983 | TraitDef(TraitDef), | ||
2984 | TypeAliasDef(TypeAliasDef), | ||
2985 | ImplDef(ImplDef), | ||
2986 | UseItem(UseItem), | ||
2987 | ExternCrateItem(ExternCrateItem), | ||
2988 | ConstDef(ConstDef), | ||
2989 | StaticDef(StaticDef), | ||
2990 | Module(Module), | ||
2991 | MacroCall(MacroCall), | ||
2992 | ExternBlock(ExternBlock), | ||
2993 | } | ||
2994 | impl From<StructDef> for ModuleItem { | 3094 | impl From<StructDef> for ModuleItem { |
2995 | fn from(node: StructDef) -> ModuleItem { ModuleItem::StructDef(node) } | 3095 | fn from(node: StructDef) -> ModuleItem { ModuleItem::StructDef(node) } |
2996 | } | 3096 | } |
@@ -3081,16 +3181,6 @@ impl AstNode for ModuleItem { | |||
3081 | } | 3181 | } |
3082 | } | 3182 | } |
3083 | } | 3183 | } |
3084 | impl ast::NameOwner for ModuleItem {} | ||
3085 | impl ast::AttrsOwner for ModuleItem {} | ||
3086 | impl ast::VisibilityOwner for ModuleItem {} | ||
3087 | |||
3088 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3089 | pub enum ImplItem { | ||
3090 | FnDef(FnDef), | ||
3091 | TypeAliasDef(TypeAliasDef), | ||
3092 | ConstDef(ConstDef), | ||
3093 | } | ||
3094 | impl From<FnDef> for ImplItem { | 3184 | impl From<FnDef> for ImplItem { |
3095 | fn from(node: FnDef) -> ImplItem { ImplItem::FnDef(node) } | 3185 | fn from(node: FnDef) -> ImplItem { ImplItem::FnDef(node) } |
3096 | } | 3186 | } |
@@ -3124,14 +3214,6 @@ impl AstNode for ImplItem { | |||
3124 | } | 3214 | } |
3125 | } | 3215 | } |
3126 | } | 3216 | } |
3127 | impl ast::NameOwner for ImplItem {} | ||
3128 | impl ast::AttrsOwner for ImplItem {} | ||
3129 | |||
3130 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3131 | pub enum ExternItem { | ||
3132 | FnDef(FnDef), | ||
3133 | StaticDef(StaticDef), | ||
3134 | } | ||
3135 | impl From<FnDef> for ExternItem { | 3217 | impl From<FnDef> for ExternItem { |
3136 | fn from(node: FnDef) -> ExternItem { ExternItem::FnDef(node) } | 3218 | fn from(node: FnDef) -> ExternItem { ExternItem::FnDef(node) } |
3137 | } | 3219 | } |
@@ -3160,44 +3242,6 @@ impl AstNode for ExternItem { | |||
3160 | } | 3242 | } |
3161 | } | 3243 | } |
3162 | } | 3244 | } |
3163 | impl ast::NameOwner for ExternItem {} | ||
3164 | impl ast::AttrsOwner for ExternItem {} | ||
3165 | impl ast::VisibilityOwner for ExternItem {} | ||
3166 | |||
3167 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3168 | pub enum Expr { | ||
3169 | TupleExpr(TupleExpr), | ||
3170 | ArrayExpr(ArrayExpr), | ||
3171 | ParenExpr(ParenExpr), | ||
3172 | PathExpr(PathExpr), | ||
3173 | LambdaExpr(LambdaExpr), | ||
3174 | IfExpr(IfExpr), | ||
3175 | LoopExpr(LoopExpr), | ||
3176 | ForExpr(ForExpr), | ||
3177 | WhileExpr(WhileExpr), | ||
3178 | ContinueExpr(ContinueExpr), | ||
3179 | BreakExpr(BreakExpr), | ||
3180 | Label(Label), | ||
3181 | BlockExpr(BlockExpr), | ||
3182 | ReturnExpr(ReturnExpr), | ||
3183 | MatchExpr(MatchExpr), | ||
3184 | RecordLit(RecordLit), | ||
3185 | CallExpr(CallExpr), | ||
3186 | IndexExpr(IndexExpr), | ||
3187 | MethodCallExpr(MethodCallExpr), | ||
3188 | FieldExpr(FieldExpr), | ||
3189 | AwaitExpr(AwaitExpr), | ||
3190 | TryExpr(TryExpr), | ||
3191 | TryBlockExpr(TryBlockExpr), | ||
3192 | CastExpr(CastExpr), | ||
3193 | RefExpr(RefExpr), | ||
3194 | PrefixExpr(PrefixExpr), | ||
3195 | RangeExpr(RangeExpr), | ||
3196 | BinExpr(BinExpr), | ||
3197 | Literal(Literal), | ||
3198 | MacroCall(MacroCall), | ||
3199 | BoxExpr(BoxExpr), | ||
3200 | } | ||
3201 | impl From<TupleExpr> for Expr { | 3245 | impl From<TupleExpr> for Expr { |
3202 | fn from(node: TupleExpr) -> Expr { Expr::TupleExpr(node) } | 3246 | fn from(node: TupleExpr) -> Expr { Expr::TupleExpr(node) } |
3203 | } | 3247 | } |
@@ -3376,26 +3420,6 @@ impl AstNode for Expr { | |||
3376 | } | 3420 | } |
3377 | } | 3421 | } |
3378 | } | 3422 | } |
3379 | impl ast::AttrsOwner for Expr {} | ||
3380 | |||
3381 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3382 | pub enum Pat { | ||
3383 | OrPat(OrPat), | ||
3384 | ParenPat(ParenPat), | ||
3385 | RefPat(RefPat), | ||
3386 | BoxPat(BoxPat), | ||
3387 | BindPat(BindPat), | ||
3388 | PlaceholderPat(PlaceholderPat), | ||
3389 | DotDotPat(DotDotPat), | ||
3390 | PathPat(PathPat), | ||
3391 | RecordPat(RecordPat), | ||
3392 | TupleStructPat(TupleStructPat), | ||
3393 | TuplePat(TuplePat), | ||
3394 | SlicePat(SlicePat), | ||
3395 | RangePat(RangePat), | ||
3396 | LiteralPat(LiteralPat), | ||
3397 | MacroPat(MacroPat), | ||
3398 | } | ||
3399 | impl From<OrPat> for Pat { | 3423 | impl From<OrPat> for Pat { |
3400 | fn from(node: OrPat) -> Pat { Pat::OrPat(node) } | 3424 | fn from(node: OrPat) -> Pat { Pat::OrPat(node) } |
3401 | } | 3425 | } |
@@ -3491,12 +3515,6 @@ impl AstNode for Pat { | |||
3491 | } | 3515 | } |
3492 | } | 3516 | } |
3493 | } | 3517 | } |
3494 | |||
3495 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3496 | pub enum RecordInnerPat { | ||
3497 | RecordFieldPat(RecordFieldPat), | ||
3498 | BindPat(BindPat), | ||
3499 | } | ||
3500 | impl From<RecordFieldPat> for RecordInnerPat { | 3518 | impl From<RecordFieldPat> for RecordInnerPat { |
3501 | fn from(node: RecordFieldPat) -> RecordInnerPat { RecordInnerPat::RecordFieldPat(node) } | 3519 | fn from(node: RecordFieldPat) -> RecordInnerPat { RecordInnerPat::RecordFieldPat(node) } |
3502 | } | 3520 | } |
@@ -3525,12 +3543,6 @@ impl AstNode for RecordInnerPat { | |||
3525 | } | 3543 | } |
3526 | } | 3544 | } |
3527 | } | 3545 | } |
3528 | |||
3529 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3530 | pub enum AttrInput { | ||
3531 | Literal(Literal), | ||
3532 | TokenTree(TokenTree), | ||
3533 | } | ||
3534 | impl From<Literal> for AttrInput { | 3546 | impl From<Literal> for AttrInput { |
3535 | fn from(node: Literal) -> AttrInput { AttrInput::Literal(node) } | 3547 | fn from(node: Literal) -> AttrInput { AttrInput::Literal(node) } |
3536 | } | 3548 | } |
@@ -3559,12 +3571,6 @@ impl AstNode for AttrInput { | |||
3559 | } | 3571 | } |
3560 | } | 3572 | } |
3561 | } | 3573 | } |
3562 | |||
3563 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3564 | pub enum Stmt { | ||
3565 | LetStmt(LetStmt), | ||
3566 | ExprStmt(ExprStmt), | ||
3567 | } | ||
3568 | impl From<LetStmt> for Stmt { | 3574 | impl From<LetStmt> for Stmt { |
3569 | fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) } | 3575 | fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) } |
3570 | } | 3576 | } |
@@ -3593,12 +3599,6 @@ impl AstNode for Stmt { | |||
3593 | } | 3599 | } |
3594 | } | 3600 | } |
3595 | } | 3601 | } |
3596 | |||
3597 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
3598 | pub enum FieldDefList { | ||
3599 | RecordFieldDefList(RecordFieldDefList), | ||
3600 | TupleFieldDefList(TupleFieldDefList), | ||
3601 | } | ||
3602 | impl From<RecordFieldDefList> for FieldDefList { | 3602 | impl From<RecordFieldDefList> for FieldDefList { |
3603 | fn from(node: RecordFieldDefList) -> FieldDefList { FieldDefList::RecordFieldDefList(node) } | 3603 | fn from(node: RecordFieldDefList) -> FieldDefList { FieldDefList::RecordFieldDefList(node) } |
3604 | } | 3604 | } |
diff --git a/crates/ra_syntax/src/ast/make.rs b/crates/ra_syntax/src/ast/make.rs index 0f4a50be4..ee0f5cc40 100644 --- a/crates/ra_syntax/src/ast/make.rs +++ b/crates/ra_syntax/src/ast/make.rs | |||
@@ -293,11 +293,20 @@ pub fn fn_def( | |||
293 | ast_from_text(&format!("fn {}{}{} {}", fn_name, type_params, params, body)) | 293 | ast_from_text(&format!("fn {}{}{} {}", fn_name, type_params, params, body)) |
294 | } | 294 | } |
295 | 295 | ||
296 | pub fn add_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { | 296 | pub fn add_leading_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { |
297 | let newlines = "\n".repeat(amount_of_newlines); | 297 | let newlines = "\n".repeat(amount_of_newlines); |
298 | ast_from_text(&format!("{}{}", newlines, t.syntax())) | 298 | ast_from_text(&format!("{}{}", newlines, t.syntax())) |
299 | } | 299 | } |
300 | 300 | ||
301 | pub fn add_trailing_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { | ||
302 | let newlines = "\n".repeat(amount_of_newlines); | ||
303 | ast_from_text(&format!("{}{}", t.syntax(), newlines)) | ||
304 | } | ||
305 | |||
306 | pub fn add_pub_crate_modifier(fn_def: ast::FnDef) -> ast::FnDef { | ||
307 | ast_from_text(&format!("pub(crate) {}", fn_def)) | ||
308 | } | ||
309 | |||
301 | fn ast_from_text<N: AstNode>(text: &str) -> N { | 310 | fn ast_from_text<N: AstNode>(text: &str) -> N { |
302 | let parse = SourceFile::parse(text); | 311 | let parse = SourceFile::parse(text); |
303 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); | 312 | let node = parse.tree().syntax().descendants().find_map(N::cast).unwrap(); |
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs index 3be648c2a..ecbfffcf4 100644 --- a/crates/ra_syntax/src/ptr.rs +++ b/crates/ra_syntax/src/ptr.rs | |||
@@ -30,10 +30,6 @@ impl SyntaxNodePtr { | |||
30 | .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) | 30 | .unwrap_or_else(|| panic!("can't resolve local ptr to SyntaxNode: {:?}", self)) |
31 | } | 31 | } |
32 | 32 | ||
33 | pub fn range(&self) -> TextRange { | ||
34 | self.range | ||
35 | } | ||
36 | |||
37 | pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> { | 33 | pub fn cast<N: AstNode>(self) -> Option<AstPtr<N>> { |
38 | if !N::can_cast(self.kind) { | 34 | if !N::can_cast(self.kind) { |
39 | return None; | 35 | return None; |
diff --git a/crates/rust-analyzer/src/bin/args.rs b/crates/rust-analyzer/src/bin/args.rs index 5e19253a6..8e3ca9343 100644 --- a/crates/rust-analyzer/src/bin/args.rs +++ b/crates/rust-analyzer/src/bin/args.rs | |||
@@ -75,6 +75,10 @@ impl Args { | |||
75 | let subcommand = match matches.subcommand()? { | 75 | let subcommand = match matches.subcommand()? { |
76 | Some(it) => it, | 76 | Some(it) => it, |
77 | None => { | 77 | None => { |
78 | if matches.contains(["-h", "--help"]) { | ||
79 | print_subcommands(); | ||
80 | return Ok(Err(HelpPrinted)); | ||
81 | } | ||
78 | matches.finish().or_else(handle_extra_flags)?; | 82 | matches.finish().or_else(handle_extra_flags)?; |
79 | return Ok(Ok(Args { verbosity, command: Command::RunServer })); | 83 | return Ok(Ok(Args { verbosity, command: Command::RunServer })); |
80 | } | 84 | } |
@@ -84,7 +88,7 @@ impl Args { | |||
84 | if matches.contains(["-h", "--help"]) { | 88 | if matches.contains(["-h", "--help"]) { |
85 | eprintln!( | 89 | eprintln!( |
86 | "\ | 90 | "\ |
87 | ra-cli-parse | 91 | rust-analyzer parse |
88 | 92 | ||
89 | USAGE: | 93 | USAGE: |
90 | rust-analyzer parse [FLAGS] | 94 | rust-analyzer parse [FLAGS] |
@@ -104,7 +108,7 @@ FLAGS: | |||
104 | if matches.contains(["-h", "--help"]) { | 108 | if matches.contains(["-h", "--help"]) { |
105 | eprintln!( | 109 | eprintln!( |
106 | "\ | 110 | "\ |
107 | ra-cli-symbols | 111 | rust-analyzer symbols |
108 | 112 | ||
109 | USAGE: | 113 | USAGE: |
110 | rust-analyzer highlight [FLAGS] | 114 | rust-analyzer highlight [FLAGS] |
@@ -123,7 +127,7 @@ FLAGS: | |||
123 | if matches.contains(["-h", "--help"]) { | 127 | if matches.contains(["-h", "--help"]) { |
124 | eprintln!( | 128 | eprintln!( |
125 | "\ | 129 | "\ |
126 | ra-cli-highlight | 130 | rust-analyzer highlight |
127 | 131 | ||
128 | USAGE: | 132 | USAGE: |
129 | rust-analyzer highlight [FLAGS] | 133 | rust-analyzer highlight [FLAGS] |
@@ -143,7 +147,7 @@ FLAGS: | |||
143 | if matches.contains(["-h", "--help"]) { | 147 | if matches.contains(["-h", "--help"]) { |
144 | eprintln!( | 148 | eprintln!( |
145 | "\ | 149 | "\ |
146 | ra-cli-analysis-stats | 150 | rust-analyzer analysis-stats |
147 | 151 | ||
148 | USAGE: | 152 | USAGE: |
149 | rust-analyzer analysis-stats [FLAGS] [OPTIONS] [PATH] | 153 | rust-analyzer analysis-stats [FLAGS] [OPTIONS] [PATH] |
@@ -193,7 +197,7 @@ ARGS: | |||
193 | if matches.contains(["-h", "--help"]) { | 197 | if matches.contains(["-h", "--help"]) { |
194 | eprintln!( | 198 | eprintln!( |
195 | "\ | 199 | "\ |
196 | rust-analyzer-analysis-bench | 200 | rust-analyzer analysis-bench |
197 | 201 | ||
198 | USAGE: | 202 | USAGE: |
199 | rust-analyzer analysis-bench [FLAGS] [OPTIONS] | 203 | rust-analyzer analysis-bench [FLAGS] [OPTIONS] |
@@ -236,7 +240,7 @@ ARGS: | |||
236 | if matches.contains(["-h", "--help"]) { | 240 | if matches.contains(["-h", "--help"]) { |
237 | eprintln!( | 241 | eprintln!( |
238 | "\ | 242 | "\ |
239 | ra-cli-diagnostics | 243 | rust-analyzer diagnostics |
240 | 244 | ||
241 | USAGE: | 245 | USAGE: |
242 | rust-analyzer diagnostics [FLAGS] [PATH] | 246 | rust-analyzer diagnostics [FLAGS] [PATH] |
@@ -267,9 +271,18 @@ ARGS: | |||
267 | } | 271 | } |
268 | "proc-macro" => Command::ProcMacro, | 272 | "proc-macro" => Command::ProcMacro, |
269 | _ => { | 273 | _ => { |
270 | eprintln!( | 274 | print_subcommands(); |
271 | "\ | 275 | return Ok(Err(HelpPrinted)); |
272 | ra-cli | 276 | } |
277 | }; | ||
278 | Ok(Ok(Args { verbosity, command })) | ||
279 | } | ||
280 | } | ||
281 | |||
282 | fn print_subcommands() { | ||
283 | eprintln!( | ||
284 | "\ | ||
285 | rust-analyzer | ||
273 | 286 | ||
274 | USAGE: | 287 | USAGE: |
275 | rust-analyzer <SUBCOMMAND> | 288 | rust-analyzer <SUBCOMMAND> |
@@ -281,14 +294,11 @@ SUBCOMMANDS: | |||
281 | analysis-bench | 294 | analysis-bench |
282 | analysis-stats | 295 | analysis-stats |
283 | highlight | 296 | highlight |
297 | diagnostics | ||
298 | proc-macro | ||
284 | parse | 299 | parse |
285 | symbols" | 300 | symbols" |
286 | ); | 301 | ) |
287 | return Ok(Err(HelpPrinted)); | ||
288 | } | ||
289 | }; | ||
290 | Ok(Ok(Args { verbosity, command })) | ||
291 | } | ||
292 | } | 302 | } |
293 | 303 | ||
294 | pub(crate) struct HelpPrinted; | 304 | pub(crate) struct HelpPrinted; |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 28b67cfe2..22a84b50c 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -51,7 +51,7 @@ fn main() -> Result<()> { | |||
51 | cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)? | 51 | cli::diagnostics(path.as_ref(), load_output_dirs, with_proc_macro, all)? |
52 | } | 52 | } |
53 | 53 | ||
54 | args::Command::ProcMacro => run_proc_macro_sv()?, | 54 | args::Command::ProcMacro => run_proc_macro_srv()?, |
55 | args::Command::RunServer => run_server()?, | 55 | args::Command::RunServer => run_server()?, |
56 | args::Command::Version => println!("rust-analyzer {}", env!("REV")), | 56 | args::Command::Version => println!("rust-analyzer {}", env!("REV")), |
57 | } | 57 | } |
@@ -65,8 +65,8 @@ fn setup_logging() -> Result<()> { | |||
65 | Ok(()) | 65 | Ok(()) |
66 | } | 66 | } |
67 | 67 | ||
68 | fn run_proc_macro_sv() -> Result<()> { | 68 | fn run_proc_macro_srv() -> Result<()> { |
69 | ra_proc_macro_srv::cli::run(); | 69 | ra_proc_macro_srv::cli::run()?; |
70 | Ok(()) | 70 | Ok(()) |
71 | } | 71 | } |
72 | 72 | ||
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 942c30328..c2ece49f4 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs | |||
@@ -23,7 +23,7 @@ impl CargoTargetSpec { | |||
23 | let mut args = Vec::new(); | 23 | let mut args = Vec::new(); |
24 | let mut extra_args = Vec::new(); | 24 | let mut extra_args = Vec::new(); |
25 | match kind { | 25 | match kind { |
26 | RunnableKind::Test { test_id } => { | 26 | RunnableKind::Test { test_id, attr } => { |
27 | args.push("test".to_string()); | 27 | args.push("test".to_string()); |
28 | if let Some(spec) = spec { | 28 | if let Some(spec) = spec { |
29 | spec.push_to(&mut args); | 29 | spec.push_to(&mut args); |
@@ -33,6 +33,9 @@ impl CargoTargetSpec { | |||
33 | extra_args.push("--exact".to_string()); | 33 | extra_args.push("--exact".to_string()); |
34 | } | 34 | } |
35 | extra_args.push("--nocapture".to_string()); | 35 | extra_args.push("--nocapture".to_string()); |
36 | if attr.ignore { | ||
37 | extra_args.push("--ignored".to_string()) | ||
38 | } | ||
36 | } | 39 | } |
37 | RunnableKind::TestMod { path } => { | 40 | RunnableKind::TestMod { path } => { |
38 | args.push("test".to_string()); | 41 | args.push("test".to_string()); |
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index d442cbd63..9fa7dad71 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -162,9 +162,13 @@ pub fn analysis_stats( | |||
162 | let (_, sm) = db.body_with_source_map(f_id.into()); | 162 | let (_, sm) = db.body_with_source_map(f_id.into()); |
163 | let src = sm.expr_syntax(expr_id); | 163 | let src = sm.expr_syntax(expr_id); |
164 | if let Ok(src) = src { | 164 | if let Ok(src) = src { |
165 | let node = { | ||
166 | let root = db.parse_or_expand(src.file_id).unwrap(); | ||
167 | src.value.to_node(&root) | ||
168 | }; | ||
165 | let original_file = src.file_id.original_file(db); | 169 | let original_file = src.file_id.original_file(db); |
166 | let line_index = host.analysis().file_line_index(original_file).unwrap(); | 170 | let line_index = host.analysis().file_line_index(original_file).unwrap(); |
167 | let text_range = src.value.syntax_node_ptr().range(); | 171 | let text_range = node.syntax().text_range(); |
168 | let (start, end) = ( | 172 | let (start, end) = ( |
169 | line_index.line_col(text_range.start()), | 173 | line_index.line_col(text_range.start()), |
170 | line_index.line_col(text_range.end()), | 174 | line_index.line_col(text_range.end()), |
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs index 762f776fe..d0a71120a 100644 --- a/crates/rust-analyzer/src/cli/load_cargo.rs +++ b/crates/rust-analyzer/src/cli/load_cargo.rs | |||
@@ -76,7 +76,7 @@ pub(crate) fn load_cargo( | |||
76 | ProcMacroClient::dummy() | 76 | ProcMacroClient::dummy() |
77 | } else { | 77 | } else { |
78 | let path = std::env::current_exe()?; | 78 | let path = std::env::current_exe()?; |
79 | ProcMacroClient::extern_process(&path, &["proc-macro"]).unwrap() | 79 | ProcMacroClient::extern_process(path, &["proc-macro"]).unwrap() |
80 | }; | 80 | }; |
81 | let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client); | 81 | let host = load(&source_roots, ws, &mut vfs, receiver, extern_dirs, &proc_macro_client); |
82 | Ok((host, source_roots)) | 82 | Ok((host, source_roots)) |
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs index 3597a14e3..715eddadb 100644 --- a/crates/rust-analyzer/src/config.rs +++ b/crates/rust-analyzer/src/config.rs | |||
@@ -7,6 +7,8 @@ | |||
7 | //! configure the server itself, feature flags are passed into analysis, and | 7 | //! configure the server itself, feature flags are passed into analysis, and |
8 | //! tweak things like automatic insertion of `()` in completions. | 8 | //! tweak things like automatic insertion of `()` in completions. |
9 | 9 | ||
10 | use std::{ffi::OsString, path::PathBuf}; | ||
11 | |||
10 | use lsp_types::TextDocumentClientCapabilities; | 12 | use lsp_types::TextDocumentClientCapabilities; |
11 | use ra_flycheck::FlycheckConfig; | 13 | use ra_flycheck::FlycheckConfig; |
12 | use ra_ide::{CompletionConfig, InlayHintsConfig}; | 14 | use ra_ide::{CompletionConfig, InlayHintsConfig}; |
@@ -20,7 +22,7 @@ pub struct Config { | |||
20 | pub with_sysroot: bool, | 22 | pub with_sysroot: bool, |
21 | pub publish_diagnostics: bool, | 23 | pub publish_diagnostics: bool, |
22 | pub lru_capacity: Option<usize>, | 24 | pub lru_capacity: Option<usize>, |
23 | pub proc_macro_srv: Option<(String, Vec<String>)>, | 25 | pub proc_macro_srv: Option<(PathBuf, Vec<OsString>)>, |
24 | pub files: FilesConfig, | 26 | pub files: FilesConfig, |
25 | pub notifications: NotificationsConfig, | 27 | pub notifications: NotificationsConfig, |
26 | 28 | ||
@@ -102,6 +104,7 @@ impl Default for Config { | |||
102 | enable_postfix_completions: true, | 104 | enable_postfix_completions: true, |
103 | add_call_parenthesis: true, | 105 | add_call_parenthesis: true, |
104 | add_call_argument_snippets: true, | 106 | add_call_argument_snippets: true, |
107 | ..CompletionConfig::default() | ||
105 | }, | 108 | }, |
106 | call_info_full: true, | 109 | call_info_full: true, |
107 | } | 110 | } |
@@ -118,7 +121,7 @@ impl Config { | |||
118 | self.client_caps = client_caps; | 121 | self.client_caps = client_caps; |
119 | 122 | ||
120 | set(value, "/withSysroot", &mut self.with_sysroot); | 123 | set(value, "/withSysroot", &mut self.with_sysroot); |
121 | set(value, "/featureFlags/lsp.diagnostics", &mut self.publish_diagnostics); | 124 | set(value, "/diagnostics/enable", &mut self.publish_diagnostics); |
122 | set(value, "/lruCapacity", &mut self.lru_capacity); | 125 | set(value, "/lruCapacity", &mut self.lru_capacity); |
123 | self.files.watcher = match get(value, "/files/watcher") { | 126 | self.files.watcher = match get(value, "/files/watcher") { |
124 | Some("client") => FilesWatcher::Client, | 127 | Some("client") => FilesWatcher::Client, |
@@ -132,10 +135,10 @@ impl Config { | |||
132 | set(value, "/cargo/features", &mut self.cargo.features); | 135 | set(value, "/cargo/features", &mut self.cargo.features); |
133 | set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); | 136 | set(value, "/cargo/loadOutDirsFromCheck", &mut self.cargo.load_out_dirs_from_check); |
134 | 137 | ||
135 | match get::<bool>(value, "/procMacro/enabled") { | 138 | match get(value, "/procMacro/enable") { |
136 | Some(true) => { | 139 | Some(true) => { |
137 | if let Ok(path) = std::env::current_exe() { | 140 | if let Ok(path) = std::env::current_exe() { |
138 | self.proc_macro_srv = Some((path.to_string_lossy().to_string(), vec!["proc-macro".to_string()])); | 141 | self.proc_macro_srv = Some((path, vec!["proc-macro".into()])); |
139 | } | 142 | } |
140 | } | 143 | } |
141 | _ => self.proc_macro_srv = None, | 144 | _ => self.proc_macro_srv = None, |
@@ -212,5 +215,13 @@ impl Config { | |||
212 | if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) { | 215 | if let Some(value) = caps.folding_range.as_ref().and_then(|it| it.line_folding_only) { |
213 | self.client_caps.line_folding_only = value | 216 | self.client_caps.line_folding_only = value |
214 | } | 217 | } |
218 | self.completion.allow_snippets(false); | ||
219 | if let Some(completion) = &caps.completion { | ||
220 | if let Some(completion_item) = &completion.completion_item { | ||
221 | if let Some(value) = completion_item.snippet_support { | ||
222 | self.completion.allow_snippets(value); | ||
223 | } | ||
224 | } | ||
225 | } | ||
215 | } | 226 | } |
216 | } | 227 | } |
diff --git a/crates/rust-analyzer/src/conv.rs b/crates/rust-analyzer/src/conv.rs index b2b1cb625..2285cb1d3 100644 --- a/crates/rust-analyzer/src/conv.rs +++ b/crates/rust-analyzer/src/conv.rs | |||
@@ -24,7 +24,9 @@ use crate::{ | |||
24 | world::WorldSnapshot, | 24 | world::WorldSnapshot, |
25 | Result, | 25 | Result, |
26 | }; | 26 | }; |
27 | use semantic_tokens::{ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION}; | 27 | use semantic_tokens::{ |
28 | ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION, UNRESOLVED_REFERENCE, | ||
29 | }; | ||
28 | 30 | ||
29 | pub trait Conv { | 31 | pub trait Conv { |
30 | type Output; | 32 | type Output; |
@@ -98,6 +100,7 @@ impl Conv for CompletionItemKind { | |||
98 | CompletionItemKind::Method => Method, | 100 | CompletionItemKind::Method => Method, |
99 | CompletionItemKind::TypeParam => TypeParameter, | 101 | CompletionItemKind::TypeParam => TypeParameter, |
100 | CompletionItemKind::Macro => Method, | 102 | CompletionItemKind::Macro => Method, |
103 | CompletionItemKind::Attribute => EnumMember, | ||
101 | } | 104 | } |
102 | } | 105 | } |
103 | } | 106 | } |
@@ -123,7 +126,7 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem { | |||
123 | for atom_edit in self.text_edit().as_atoms() { | 126 | for atom_edit in self.text_edit().as_atoms() { |
124 | if self.source_range().is_subrange(&atom_edit.delete) { | 127 | if self.source_range().is_subrange(&atom_edit.delete) { |
125 | text_edit = Some(if atom_edit.delete == self.source_range() { | 128 | text_edit = Some(if atom_edit.delete == self.source_range() { |
126 | atom_edit.conv_with(ctx) | 129 | atom_edit.conv_with((ctx.0, ctx.1)) |
127 | } else { | 130 | } else { |
128 | assert!(self.source_range().end() == atom_edit.delete.end()); | 131 | assert!(self.source_range().end() == atom_edit.delete.end()); |
129 | let range1 = | 132 | let range1 = |
@@ -131,12 +134,12 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem { | |||
131 | let range2 = self.source_range(); | 134 | let range2 = self.source_range(); |
132 | let edit1 = AtomTextEdit::replace(range1, String::new()); | 135 | let edit1 = AtomTextEdit::replace(range1, String::new()); |
133 | let edit2 = AtomTextEdit::replace(range2, atom_edit.insert.clone()); | 136 | let edit2 = AtomTextEdit::replace(range2, atom_edit.insert.clone()); |
134 | additional_text_edits.push(edit1.conv_with(ctx)); | 137 | additional_text_edits.push(edit1.conv_with((ctx.0, ctx.1))); |
135 | edit2.conv_with(ctx) | 138 | edit2.conv_with((ctx.0, ctx.1)) |
136 | }) | 139 | }) |
137 | } else { | 140 | } else { |
138 | assert!(self.source_range().intersection(&atom_edit.delete).is_none()); | 141 | assert!(self.source_range().intersection(&atom_edit.delete).is_none()); |
139 | additional_text_edits.push(atom_edit.conv_with(ctx)); | 142 | additional_text_edits.push(atom_edit.conv_with((ctx.0, ctx.1))); |
140 | } | 143 | } |
141 | } | 144 | } |
142 | let text_edit = text_edit.unwrap(); | 145 | let text_edit = text_edit.unwrap(); |
@@ -163,6 +166,10 @@ impl ConvWith<(&LineIndex, LineEndings)> for CompletionItem { | |||
163 | ..Default::default() | 166 | ..Default::default() |
164 | }; | 167 | }; |
165 | 168 | ||
169 | if self.score().is_some() { | ||
170 | res.preselect = Some(true) | ||
171 | } | ||
172 | |||
166 | if self.deprecated() { | 173 | if self.deprecated() { |
167 | res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated]) | 174 | res.tags = Some(vec![lsp_types::CompletionItemTag::Deprecated]) |
168 | } | 175 | } |
@@ -373,6 +380,7 @@ impl Conv for Highlight { | |||
373 | HighlightTag::Comment => SemanticTokenType::COMMENT, | 380 | HighlightTag::Comment => SemanticTokenType::COMMENT, |
374 | HighlightTag::Attribute => ATTRIBUTE, | 381 | HighlightTag::Attribute => ATTRIBUTE, |
375 | HighlightTag::Keyword => SemanticTokenType::KEYWORD, | 382 | HighlightTag::Keyword => SemanticTokenType::KEYWORD, |
383 | HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE, | ||
376 | }; | 384 | }; |
377 | 385 | ||
378 | for modifier in self.modifiers.iter() { | 386 | for modifier in self.modifiers.iter() { |
diff --git a/crates/rust-analyzer/src/main_loop/handlers.rs b/crates/rust-analyzer/src/main_loop/handlers.rs index b207f0764..41d9fe344 100644 --- a/crates/rust-analyzer/src/main_loop/handlers.rs +++ b/crates/rust-analyzer/src/main_loop/handlers.rs | |||
@@ -968,7 +968,7 @@ fn to_lsp_runnable( | |||
968 | let (args, extra_args) = CargoTargetSpec::runnable_args(spec, &runnable.kind)?; | 968 | let (args, extra_args) = CargoTargetSpec::runnable_args(spec, &runnable.kind)?; |
969 | let line_index = world.analysis().file_line_index(file_id)?; | 969 | let line_index = world.analysis().file_line_index(file_id)?; |
970 | let label = match &runnable.kind { | 970 | let label = match &runnable.kind { |
971 | RunnableKind::Test { test_id } => format!("test {}", test_id), | 971 | RunnableKind::Test { test_id, .. } => format!("test {}", test_id), |
972 | RunnableKind::TestMod { path } => format!("test-mod {}", path), | 972 | RunnableKind::TestMod { path } => format!("test-mod {}", path), |
973 | RunnableKind::Bench { test_id } => format!("bench {}", test_id), | 973 | RunnableKind::Bench { test_id } => format!("bench {}", test_id), |
974 | RunnableKind::Bin => "run binary".to_string(), | 974 | RunnableKind::Bin => "run binary".to_string(), |
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index 865fa3b1c..10fe696f6 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs | |||
@@ -10,6 +10,8 @@ pub(crate) const ENUM_MEMBER: SemanticTokenType = SemanticTokenType::new("enumMe | |||
10 | pub(crate) const LIFETIME: SemanticTokenType = SemanticTokenType::new("lifetime"); | 10 | pub(crate) const LIFETIME: SemanticTokenType = SemanticTokenType::new("lifetime"); |
11 | pub(crate) const TYPE_ALIAS: SemanticTokenType = SemanticTokenType::new("typeAlias"); | 11 | pub(crate) const TYPE_ALIAS: SemanticTokenType = SemanticTokenType::new("typeAlias"); |
12 | pub(crate) const UNION: SemanticTokenType = SemanticTokenType::new("union"); | 12 | pub(crate) const UNION: SemanticTokenType = SemanticTokenType::new("union"); |
13 | pub(crate) const UNRESOLVED_REFERENCE: SemanticTokenType = | ||
14 | SemanticTokenType::new("unresolvedReference"); | ||
13 | 15 | ||
14 | pub(crate) const CONSTANT: SemanticTokenModifier = SemanticTokenModifier::new("constant"); | 16 | pub(crate) const CONSTANT: SemanticTokenModifier = SemanticTokenModifier::new("constant"); |
15 | pub(crate) const CONTROL_FLOW: SemanticTokenModifier = SemanticTokenModifier::new("controlFlow"); | 17 | pub(crate) const CONTROL_FLOW: SemanticTokenModifier = SemanticTokenModifier::new("controlFlow"); |
@@ -43,6 +45,7 @@ pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[ | |||
43 | LIFETIME, | 45 | LIFETIME, |
44 | TYPE_ALIAS, | 46 | TYPE_ALIAS, |
45 | UNION, | 47 | UNION, |
48 | UNRESOLVED_REFERENCE, | ||
46 | ]; | 49 | ]; |
47 | 50 | ||
48 | pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[ | 51 | pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[ |
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs index f2ad453fa..34941931b 100644 --- a/crates/rust-analyzer/src/world.rs +++ b/crates/rust-analyzer/src/world.rs | |||
@@ -148,20 +148,17 @@ impl WorldState { | |||
148 | 148 | ||
149 | let proc_macro_client = match &config.proc_macro_srv { | 149 | let proc_macro_client = match &config.proc_macro_srv { |
150 | None => ProcMacroClient::dummy(), | 150 | None => ProcMacroClient::dummy(), |
151 | Some((path, args)) => { | 151 | Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) { |
152 | let path = std::path::Path::new(path); | 152 | Ok(it) => it, |
153 | match ProcMacroClient::extern_process(path, args) { | 153 | Err(err) => { |
154 | Ok(it) => it, | 154 | log::error!( |
155 | Err(err) => { | 155 | "Failed to run ra_proc_macro_srv from path {}, error: {:?}", |
156 | log::error!( | 156 | path.display(), |
157 | "Fail to run ra_proc_macro_srv from path {}, error : {}", | 157 | err |
158 | path.to_string_lossy(), | 158 | ); |
159 | err | 159 | ProcMacroClient::dummy() |
160 | ); | ||
161 | ProcMacroClient::dummy() | ||
162 | } | ||
163 | } | 160 | } |
164 | } | 161 | }, |
165 | }; | 162 | }; |
166 | 163 | ||
167 | workspaces | 164 | workspaces |
@@ -184,7 +181,7 @@ impl WorldState { | |||
184 | let mut analysis_host = AnalysisHost::new(lru_capacity); | 181 | let mut analysis_host = AnalysisHost::new(lru_capacity); |
185 | analysis_host.apply_change(change); | 182 | analysis_host.apply_change(change); |
186 | WorldState { | 183 | WorldState { |
187 | config: config, | 184 | config, |
188 | roots: folder_roots, | 185 | roots: folder_roots, |
189 | workspaces: Arc::new(workspaces), | 186 | workspaces: Arc::new(workspaces), |
190 | analysis_host, | 187 | analysis_host, |
diff --git a/crates/rust-analyzer/tests/heavy_tests/main.rs b/crates/rust-analyzer/tests/heavy_tests/main.rs index 1dd2676b6..b31533e5e 100644 --- a/crates/rust-analyzer/tests/heavy_tests/main.rs +++ b/crates/rust-analyzer/tests/heavy_tests/main.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | mod support; | 1 | mod support; |
2 | 2 | ||
3 | use std::{collections::HashMap, time::Instant}; | 3 | use std::{collections::HashMap, path::PathBuf, time::Instant}; |
4 | 4 | ||
5 | use lsp_types::{ | 5 | use lsp_types::{ |
6 | CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, | 6 | CodeActionContext, DidOpenTextDocumentParams, DocumentFormattingParams, FormattingOptions, |
@@ -692,15 +692,10 @@ pub fn foo(_input: TokenStream) -> TokenStream { | |||
692 | "###, | 692 | "###, |
693 | ) | 693 | ) |
694 | .with_config(|config| { | 694 | .with_config(|config| { |
695 | // FIXME: Use env!("CARGO_BIN_EXE_ra-analyzer") instead after | 695 | let macro_srv_path = PathBuf::from(env!("CARGO_BIN_EXE_rust-analyzer")); |
696 | // https://github.com/rust-lang/cargo/pull/7697 landed | ||
697 | let macro_srv_path = std::path::Path::new(std::env!("CARGO_MANIFEST_DIR")) | ||
698 | .join("../../target/debug/rust-analyzer") | ||
699 | .to_string_lossy() | ||
700 | .to_string(); | ||
701 | 696 | ||
702 | config.cargo.load_out_dirs_from_check = true; | 697 | config.cargo.load_out_dirs_from_check = true; |
703 | config.proc_macro_srv = Some((macro_srv_path, vec!["proc-macro".to_string()])); | 698 | config.proc_macro_srv = Some((macro_srv_path, vec!["proc-macro".into()])); |
704 | }) | 699 | }) |
705 | .root("foo") | 700 | .root("foo") |
706 | .root("bar") | 701 | .root("bar") |