aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_assists/src/assist_ctx.rs8
-rw-r--r--crates/ra_assists/src/doc_tests/generated.rs4
-rw-r--r--crates/ra_assists/src/handlers/add_explicit_type.rs48
-rw-r--r--crates/ra_assists/src/handlers/add_from_impl_for_enum.rs2
-rw-r--r--crates/ra_assists/src/handlers/add_function.rs236
-rw-r--r--crates/ra_assists/src/handlers/introduce_variable.rs2
-rw-r--r--crates/ra_assists/src/handlers/merge_imports.rs2
-rw-r--r--crates/ra_assists/src/handlers/split_import.rs7
-rw-r--r--crates/ra_assists/src/lib.rs25
-rw-r--r--crates/ra_db/src/fixture.rs2
-rw-r--r--crates/ra_db/src/input.rs2
-rw-r--r--crates/ra_hir/src/code_model.rs15
-rw-r--r--crates/ra_hir/src/semantics.rs4
-rw-r--r--crates/ra_hir/src/source_analyzer.rs11
-rw-r--r--crates/ra_hir_def/src/body/lower.rs8
-rw-r--r--crates/ra_hir_def/src/body/scope.rs11
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs32
-rw-r--r--crates/ra_hir_def/src/nameres/tests.rs9
-rw-r--r--crates/ra_hir_expand/Cargo.toml1
-rw-r--r--crates/ra_hir_expand/src/ast_id_map.rs2
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs8
-rw-r--r--crates/ra_hir_expand/src/proc_macro.rs106
-rw-r--r--crates/ra_hir_ty/Cargo.toml6
-rw-r--r--crates/ra_hir_ty/src/_match.rs336
-rw-r--r--crates/ra_hir_ty/src/db.rs7
-rw-r--r--crates/ra_hir_ty/src/infer.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/pat.rs6
-rw-r--r--crates/ra_hir_ty/src/lib.rs2
-rw-r--r--crates/ra_hir_ty/src/test_db.rs36
-rw-r--r--crates/ra_hir_ty/src/tests.rs52
-rw-r--r--crates/ra_hir_ty/src/tests/patterns.rs26
-rw-r--r--crates/ra_hir_ty/src/tests/regression.rs41
-rw-r--r--crates/ra_hir_ty/src/traits.rs2
-rw-r--r--crates/ra_hir_ty/src/traits/chalk.rs145
-rw-r--r--crates/ra_hir_ty/src/traits/chalk/tls.rs33
-rw-r--r--crates/ra_ide/src/assists.rs4
-rw-r--r--crates/ra_ide/src/call_info.rs30
-rw-r--r--crates/ra_ide/src/completion.rs25
-rw-r--r--crates/ra_ide/src/completion/complete_attribute.rs587
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs6
-rw-r--r--crates/ra_ide/src/completion/complete_keyword.rs12
-rw-r--r--crates/ra_ide/src/completion/complete_macro_in_item_position.rs6
-rw-r--r--crates/ra_ide/src/completion/complete_pattern.rs2
-rw-r--r--crates/ra_ide/src/completion/complete_postfix.rs39
-rw-r--r--crates/ra_ide/src/completion/complete_qualified_path.rs46
-rw-r--r--crates/ra_ide/src/completion/complete_snippet.rs26
-rw-r--r--crates/ra_ide/src/completion/complete_trait_impl.rs18
-rw-r--r--crates/ra_ide/src/completion/complete_unqualified_path.rs229
-rw-r--r--crates/ra_ide/src/completion/completion_config.rs35
-rw-r--r--crates/ra_ide/src/completion/completion_context.rs31
-rw-r--r--crates/ra_ide/src/completion/completion_item.rs38
-rw-r--r--crates/ra_ide/src/completion/presentation.rs419
-rw-r--r--crates/ra_ide/src/display/function_signature.rs69
-rw-r--r--crates/ra_ide/src/display/navigation_target.rs2
-rw-r--r--crates/ra_ide/src/extend_selection.rs2
-rw-r--r--crates/ra_ide/src/goto_definition.rs28
-rw-r--r--crates/ra_ide/src/lib.rs4
-rw-r--r--crates/ra_ide/src/marks.rs2
-rw-r--r--crates/ra_ide/src/runnables.rs35
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html6
-rw-r--r--crates/ra_ide/src/snapshots/rainbow_highlighting.html6
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs37
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tags.rs2
-rw-r--r--crates/ra_ide_db/src/defs.rs9
-rw-r--r--crates/ra_ide_db/src/marks.rs1
-rw-r--r--crates/ra_ide_db/src/symbol_index.rs2
-rw-r--r--crates/ra_mbe/src/mbe_expander/matcher.rs40
-rw-r--r--crates/ra_mbe/src/subtree_source.rs47
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs39
-rw-r--r--crates/ra_mbe/src/tests.rs57
-rw-r--r--crates/ra_mbe/src/tt_iter.rs8
-rw-r--r--crates/ra_proc_macro/src/lib.rs17
-rw-r--r--crates/ra_proc_macro/src/msg.rs37
-rw-r--r--crates/ra_proc_macro/src/process.rs118
-rw-r--r--crates/ra_proc_macro/src/rpc.rs18
-rw-r--r--crates/ra_proc_macro_srv/src/cli.rs69
-rw-r--r--crates/ra_proc_macro_srv/src/dylib.rs103
-rw-r--r--crates/ra_proc_macro_srv/src/lib.rs36
-rw-r--r--crates/ra_proc_macro_srv/src/rustc_server.rs13
-rw-r--r--crates/ra_proc_macro_srv/src/tests/fixtures/test_serialize_proc_macro.txt3
-rw-r--r--crates/ra_proc_macro_srv/src/tests/utils.rs2
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs8
-rw-r--r--crates/ra_syntax/src/algo.rs8
-rw-r--r--crates/ra_syntax/src/ast/edit.rs6
-rw-r--r--crates/ra_syntax/src/ast/generated/nodes.rs2924
-rw-r--r--crates/ra_syntax/src/ast/make.rs11
-rw-r--r--crates/ra_syntax/src/ptr.rs4
-rw-r--r--crates/rust-analyzer/src/bin/args.rs40
-rw-r--r--crates/rust-analyzer/src/bin/main.rs6
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs5
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs6
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs19
-rw-r--r--crates/rust-analyzer/src/conv.rs18
-rw-r--r--crates/rust-analyzer/src/main_loop/handlers.rs2
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs3
-rw-r--r--crates/rust-analyzer/src/world.rs25
-rw-r--r--crates/rust-analyzer/tests/heavy_tests/main.rs11
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};
11use ra_text_edit::TextEditBuilder; 11use ra_text_edit::TextEditBuilder;
12 12
13use crate::{AssistAction, AssistId, AssistLabel, GroupLabel, ResolvedAssist}; 13use crate::{AssistAction, AssistFile, AssistId, AssistLabel, GroupLabel, ResolvedAssist};
14use algo::SyntaxRewriter; 14use 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
185impl ActionBuilder { 186impl 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() {
66struct Baz; 66struct Baz;
67fn baz() -> Baz { Baz } 67fn baz() -> Baz { Baz }
68fn foo() { 68fn foo() {
69 bar<|>("", baz()); 69 bar<|>("", baz());
70} 70}
71 71
72"#####, 72"#####,
@@ -74,7 +74,7 @@ fn foo() {
74struct Baz; 74struct Baz;
75fn baz() -> Baz { Baz } 75fn baz() -> Baz { Baz }
76fn foo() { 76fn foo() {
77 bar("", baz()); 77 bar("", baz());
78} 78}
79 79
80fn bar(arg: &str, baz: Baz) { 80fn 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#"
184fn 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#"
196struct Test<K, T = u8> {
197 k: K,
198 t: T,
199}
200
201fn main() {
202 let test<|> = Test { t: 23, k: 33 };
203}"#,
204 r#"
205struct Test<K, T = u8> {
206 k: K,
207 t: T,
208}
209
210fn 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
6use crate::{Assist, AssistCtx, AssistId}; 6use crate::{Assist, AssistCtx, AssistFile, AssistId};
7use ast::{edit::IndentLevel, ArgListOwner, CallExpr, Expr}; 7use ast::{edit::IndentLevel, ArgListOwner, ModuleItemOwner};
8use hir::HirDisplay; 8use hir::HirDisplay;
9use rustc_hash::{FxHashMap, FxHashSet}; 9use 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
68struct FunctionBuilder { 78struct 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
75impl FunctionBuilder { 87impl 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
101fn fn_name(call: &CallExpr) -> Option<ast::Name> { 148enum GeneratedFunctionTarget {
102 let name = call.expr()?.syntax().to_string(); 149 BehindItem(SyntaxNode),
150 InEmptyItemList(ast::ItemList),
151}
152
153fn 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
107fn fn_args( 159fn 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
161fn fn_arg_name(fn_arg: &Expr) -> Option<String> { 213fn 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
175fn fn_arg_type(ctx: &AssistCtx, fn_arg: &Expr) -> Option<String> { 227fn 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
187fn next_space_for_fn(expr: &CallExpr) -> Option<SyntaxNode> { 239fn 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
259fn 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"
798mod bar {}
799
800fn foo() {
801 bar::my_fn<|>()
802}
803",
804 r"
805mod bar {
806 pub(crate) fn my_fn() {
807 <|>todo!()
808 }
809}
810
811fn 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"
823mod bar {
824 fn something_else() {}
825}
826
827fn foo() {
828 bar::my_fn<|>()
829}
830",
831 r"
832mod bar {
833 fn something_else() {}
834
835 pub(crate) fn my_fn() {
836 <|>todo!()
837 }
838}
839
840fn 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"
852mod bar {
853 mod baz {}
854}
855
856fn foo() {
857 bar::baz::my_fn<|>()
858}
859",
860 r"
861mod bar {
862 mod baz {
863 pub(crate) fn my_fn() {
864 <|>todo!()
865 }
866 }
867}
868
869fn 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
882mod foo;
883
884fn main() {
885 foo::bar<|>()
886}
887//- /foo.rs
888",
889 r"
890
891
892pub(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)]
39mod tests { 39mod 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;
17pub mod utils; 17pub mod utils;
18pub mod ast_transform; 18pub mod ast_transform;
19 19
20use ra_db::FileRange; 20use ra_db::{FileId, FileRange};
21use ra_ide_db::RootDatabase; 21use ra_ide_db::RootDatabase;
22use ra_syntax::{TextRange, TextUnit}; 22use ra_syntax::{TextRange, TextUnit};
23use ra_text_edit::TextEdit; 23use 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)]
68pub enum AssistFile {
69 CurrentFile,
70 TargetFile(FileId),
71}
72
73impl 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]
26fn crate_def_map_smoke_test() { 26fn 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" }
18ra_prof = { path = "../ra_prof" } 18ra_prof = { path = "../ra_prof" }
19tt = { path = "../ra_tt", package = "ra_tt" } 19tt = { path = "../ra_tt", package = "ra_tt" }
20mbe = { path = "../ra_mbe", package = "ra_mbe" } 20mbe = { path = "../ra_mbe", package = "ra_mbe" }
21test_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
3use crate::{db::AstDatabase, LazyMacroId}; 3use crate::{db::AstDatabase, LazyMacroId};
4use ra_db::{CrateId, ProcMacroId}; 4use ra_db::{CrateId, ProcMacroId};
5use tt::buffer::{Cursor, TokenBuffer};
5 6
6#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)] 7#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
7pub struct ProcMacroExpander { 8pub 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
46fn remove_derive_atr(tt: &tt::Subtree, _name: &str) -> Option<tt::Subtree> { 47fn 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
57fn 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
67fn 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
77fn 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)]
104mod 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#"
127SUBTREE $
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
28scoped-tls = "1" 28scoped-tls = "1"
29 29
30chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "28cef6ff403d403e6ad2f3d27d944e9ffac1bce8" } 30chalk-solve = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" }
31chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "28cef6ff403d403e6ad2f3d27d944e9ffac1bce8" } 31chalk-rust-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" }
32chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "28cef6ff403d403e6ad2f3d27d944e9ffac1bce8" } 32chalk-ir = { git = "https://github.com/rust-lang/chalk.git", rev = "2c072cc830d04af5f10b390e6643327f85108282" }
33 33
34[dev-dependencies] 34[dev-dependencies]
35insta = "0.16.0" 35insta = "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
238impl 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)]
239pub enum MatchCheckErr { 245pub 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
112fn infer_wait(db: &impl HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { 119fn 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};
11use hir_expand::name::Name; 12use hir_expand::name::Name;
12use test_utils::tested_by; 13use 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};
13use stdx::format_to; 13use stdx::format_to;
14 14
15use crate::{db::HirDatabase, expr::ExprValidator}; 15use 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};
21use hir_expand::InFile; 21use hir_expand::{db::AstDatabase, InFile};
22use insta::assert_snapshot; 22use insta::assert_snapshot;
23use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase}; 23use ra_db::{fixture::WithFixture, salsa::Database, FilePosition, SourceDatabase};
24use ra_syntax::{ 24use ra_syntax::{
25 algo, 25 algo,
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
27 SyntaxNode,
27}; 28};
28use stdx::format_to; 29use stdx::format_to;
29 30
30use crate::{db::HirDatabase, display::HirDisplay, test_db::TestDB, InferenceResult}; 31use 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]
460fn infer_guard() {
461 assert_snapshot!(
462 infer(r#"
463struct S;
464impl S { fn foo(&self) -> bool { false } }
465
466fn 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]
538fn issue_4053_diesel_where_clauses() {
539 assert_snapshot!(
540 infer(r#"
541trait BoxedDsl<DB> {
542 type Output;
543 fn internal_into_boxed(self) -> Self::Output;
544}
545
546struct SelectStatement<From, Select, Distinct, Where, Order, LimitOffset, GroupBy, Locking> {
547 order: Order,
548}
549
550trait QueryFragment<DB: Backend> {}
551
552trait Into<T> { fn into(self) -> T; }
553
554impl<F, S, D, W, O, LOf, DB> BoxedDsl<DB>
555 for SelectStatement<F, S, D, W, O, LOf, G>
556where
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};
4use log::debug; 4use log::debug;
5 5
6use chalk_ir::{ 6use 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
11use hir_def::{AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId}; 11use 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 &parameter_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
231impl chalk_ir::interner::HasInterner for Interner { 282impl 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
492impl ToChalk for ProjectionTy { 555impl 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 {
540impl<T> ToChalk for Canonical<T> 606impl<T> ToChalk for Canonical<T>
541where 607where
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
652fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { 725fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
726where
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
897pub(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
804pub(crate) fn associated_ty_data_query( 905pub(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 {}", &params[0], trait_data.name,)?; 156 write!(fmt, "<{:?} as {}", &params[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
22pub(crate) fn call_info_for_token( 22#[derive(Debug)]
23 sema: &Semantics<RootDatabase>, 23pub(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
29impl 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
39fn 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
162impl CallInfo { 176impl 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
3mod completion_config;
3mod completion_item; 4mod completion_item;
4mod completion_context; 5mod completion_context;
5mod presentation; 6mod presentation;
6 7
8mod complete_attribute;
7mod complete_dot; 9mod complete_dot;
8mod complete_record; 10mod complete_record;
9mod complete_pattern; 11mod complete_pattern;
@@ -28,27 +30,11 @@ use crate::{
28 FilePosition, 30 FilePosition,
29}; 31};
30 32
31pub use crate::completion::completion_item::{ 33pub 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)]
36pub struct CompletionConfig {
37 pub enable_postfix_completions: bool,
38 pub add_call_parenthesis: bool,
39 pub add_call_argument_snippets: bool,
40}
41
42impl 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
6use super::completion_context::CompletionContext;
7use super::completion_item::{CompletionItem, CompletionItemKind, CompletionKind, Completions};
8use ra_syntax::{
9 ast::{Attr, AttrKind},
10 AstNode,
11};
12
13pub(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
46struct AttrCompletion {
47 label: &'static str,
48 snippet: Option<&'static str>,
49 should_be_inner: bool,
50}
51
52const 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)]
130mod 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
3use hir::{HasVisibility, Type}; 3use hir::{HasVisibility, Type};
4 4
5use crate::completion::completion_item::CompletionKind;
6use crate::{ 5use 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};
10use rustc_hash::FxHashSet; 12use 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
44fn keyword(ctx: &CompletionContext, kw: &str, snippet: &str) -> CompletionItem { 44fn 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
51pub(super) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) { 55pub(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};
7use ra_text_edit::TextEdit; 7use ra_text_edit::TextEdit;
8 8
9use super::completion_config::SnippetCap;
9use crate::{ 10use 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
89fn get_receiver_text(receiver: &ast::Expr, receiver_is_ambiguous_float_literal: bool) -> String { 115fn 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
109fn postfix_snippet( 135fn 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
3use crate::completion::{ 3use 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
8fn snippet(ctx: &CompletionContext, label: &str, snippet: &str) -> Builder { 8fn 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
23pub(super) fn complete_item_snippet(acc: &mut Completions, ctx: &CompletionContext) { 27pub(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
152fn add_type_alias_impl( 160fn 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;
4use test_utils::tested_by; 4use test_utils::tested_by;
5 5
6use crate::completion::{CompletionContext, Completions}; 6use crate::completion::{CompletionContext, Completions};
7use hir::{Adt, ModuleDef};
7use ra_syntax::AstNode; 8use ra_syntax::AstNode;
8 9
9pub(super) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionContext) { 10pub(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
37fn 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)]
35mod tests { 56mod 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)]
8pub 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
15impl 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)]
22pub struct SnippetCap {
23 _private: (),
24}
25
26impl 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
3use hir::{Semantics, SemanticsScope}; 3use hir::{Semantics, SemanticsScope, Type};
4use ra_db::SourceDatabase; 4use ra_db::SourceDatabase;
5use ra_ide_db::RootDatabase; 5use ra_ide_db::RootDatabase;
6use ra_syntax::{ 6use ra_syntax::{
@@ -11,7 +11,7 @@ use ra_syntax::{
11}; 11};
12use ra_text_edit::AtomTextEdit; 12use ra_text_edit::AtomTextEdit;
13 13
14use crate::{completion::CompletionConfig, FilePosition}; 14use 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
59impl<'a> CompletionContext<'a> { 63impl<'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
3use std::fmt; 3use std::fmt;
4 4
5use super::completion_config::SnippetCap;
5use hir::Documentation; 6use hir::Documentation;
6use ra_syntax::TextRange; 7use ra_syntax::TextRange;
7use ra_text_edit::TextEdit; 8use 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)]
98pub 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)]
91pub enum CompletionItemKind { 106pub 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
211impl Builder { 234impl 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
17impl Completions { 17impl 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(&macro_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(), &macro_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
295pub(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
297enum Params { 331enum 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
390fn 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(&macro_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)]
353mod tests { 419mod 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
152impl From<&'_ ast::FnDef> for FunctionSignature { 169impl 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
63impl ReferenceResult { 63impl 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;
67pub use crate::{ 67pub 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)]
36pub enum RunnableKind { 36pub 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)]
92pub struct TestAttr {
93 pub ignore: bool,
94}
95
96impl 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};
20use rustc_hash::FxHashMap; 20use rustc_hash::FxHashMap;
21 21
22use crate::{call_info::call_info_for_token, Analysis, FileId}; 22use crate::{call_info::ActiveParameter, Analysis, FileId};
23 23
24use ast::FormatSpecifier; 24use ast::FormatSpecifier;
25pub(crate) use html::highlight_as_html; 25pub(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)]
183pub enum NameRefClass { 184pub 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(&macro_call) { 243 if let Some(macro_def) = sema.resolve_macro_call(&macro_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
144fn convert_ident(ident: &tt::Ident) -> TtToken { 166fn 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
154fn convert_punct(p: tt::Punct) -> TtToken { 177fn 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
274trait SrcToken { 274trait 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)]
458enum SynToken { 482enum 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
594impl<'a> TreeSink for TtTreeSink<'a> { 618impl<'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]
218fn test_lifetime_split() {
219 parse_macro(
220 r#"
221macro_rules! foo {
222 ($($t:tt)*) => { $($t)*}
223}
224"#,
225 )
226 .assert_expand(
227 r#"foo!(static bar: &'static str = "hello";);"#,
228 r#"
229SUBTREE $
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]
218fn test_expr_order() { 245fn 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]
1019fn 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#"
1030SUBTREE $
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]
992fn test_vis() { 1049fn 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
8mod rpc; 8mod rpc;
@@ -13,6 +13,7 @@ use process::{ProcMacroProcessSrv, ProcMacroProcessThread};
13use ra_tt::{SmolStr, Subtree}; 13use ra_tt::{SmolStr, Subtree};
14use std::{ 14use 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
59impl ProcMacroClient { 60impl 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
3use std::{ 3use 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
56pub trait Message: Sized + Serialize + DeserializeOwned { 56pub 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
74fn read_json(inp: &mut impl BufRead) -> io::Result<Option<String>> { 72fn 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
87fn write_json(out: &mut impl Write, msg: &str) -> io::Result<()> { 82fn 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
9use io::{BufRead, BufReader}; 9use io::{BufRead, BufReader};
10use std::{ 10use 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
31struct Task {
32 req: Request,
33 result_tx: Sender<Option<Response>>,
34}
35
36struct Process {
37 path: PathBuf,
38 child: Child,
39}
40
41impl Drop for Process {
42 fn drop(&mut self) {
43 let _ = self.child.kill();
44 }
45}
46
47impl 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
82impl ProcMacroProcessSrv { 31impl 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
145struct Task {
146 req: Request,
147 result_tx: Sender<Option<Response>>,
148}
149
150struct Process {
151 path: PathBuf,
152 args: Vec<OsString>,
153 child: Child,
154}
155
156impl Drop for Process {
157 fn drop(&mut self) {
158 let _ = self.child.kill();
159 }
160}
161
162impl 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
187fn 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
200fn send_request( 196fn 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
9use ra_tt::{ 9use ra_tt::{
@@ -34,15 +34,15 @@ pub struct ListMacrosResult {
34pub struct ExpansionTask { 34pub 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
3use crate::{expand_task, list_macros}; 3use crate::{expand_task, list_macros};
4use ra_proc_macro::msg::{self, Message}; 4use ra_proc_macro::msg::{self, Message};
5
6use std::io; 5use std::io;
7 6
8fn read_request() -> Result<Option<msg::Request>, io::Error> { 7pub 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)
14fn 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
28pub 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
31fn read_request() -> io::Result<Option<msg::Request>> {
32 msg::Request::read(&mut io::stdin().lock())
33}
34
35fn 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;
9use memmap::Mmap; 9use memmap::Mmap;
10use ra_proc_macro::ProcMacroKind; 10use ra_proc_macro::ProcMacroKind;
11 11
12use std::io::Error as IoError; 12use std::io;
13use std::io::ErrorKind as IoErrorKind;
14 13
15const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_"; 14const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
16 15
17fn invalid_data_err(e: impl Into<Box<dyn std::error::Error + Send + Sync>>) -> IoError { 16fn 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
21fn is_derive_registrar_symbol(symbol: &str) -> bool { 20fn is_derive_registrar_symbol(symbol: &str) -> bool {
22 symbol.contains(NEW_REGISTRAR_SYMBOL) 21 symbol.contains(NEW_REGISTRAR_SYMBOL)
23} 22}
24 23
25fn find_registrar_symbol(file: &Path) -> Result<Option<String>, IoError> { 24fn 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
95struct ProcMacroLibraryLibloading { 89struct 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
101impl ProcMacroLibraryLibloading { 95impl 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
123impl Expander { 118impl 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
22use proc_macro::bridge::client::TokenStream; 22use proc_macro::bridge::client::TokenStream;
23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask}; 23use ra_proc_macro::{ExpansionResult, ExpansionTask, ListMacrosResult, ListMacrosTask};
24use std::path::Path;
24 25
25pub(crate) fn expand_task(task: &ExpansionTask) -> Result<ExpansionResult, String> { 26pub(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
42pub(crate) fn list_macros(task: &ListMacrosTask) -> Result<ListMacrosResult, String> { 37pub(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 = 43fn 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
56pub mod cli; 48pub 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
11use crate::proc_macro::bridge::{self, server}; 11use crate::proc_macro::bridge::{self, server};
12use ra_tt as tt; 12use ra_tt as tt;
@@ -76,7 +76,16 @@ impl Extend<TokenTree> for TokenStream {
76impl Extend<TokenStream> for TokenStream { 76impl 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;
10use rustc_hash::FxHashMap; 10use rustc_hash::FxHashMap;
11 11
12use crate::{ 12use 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
93pub 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)]
94pub enum InsertPosition<T> { 98pub 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::{
10pub struct SourceFile { 10pub struct SourceFile {
11 pub(crate) syntax: SyntaxNode, 11 pub(crate) syntax: SyntaxNode,
12} 12}
13impl 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}
24impl ast::ModuleItemOwner for SourceFile {} 13impl ast::ModuleItemOwner for SourceFile {}
25impl ast::AttrsOwner for SourceFile {} 14impl ast::AttrsOwner for SourceFile {}
26impl SourceFile { 15impl SourceFile {
@@ -31,17 +20,6 @@ impl SourceFile {
31pub struct FnDef { 20pub struct FnDef {
32 pub(crate) syntax: SyntaxNode, 21 pub(crate) syntax: SyntaxNode,
33} 22}
34impl 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}
45impl ast::VisibilityOwner for FnDef {} 23impl ast::VisibilityOwner for FnDef {}
46impl ast::NameOwner for FnDef {} 24impl ast::NameOwner for FnDef {}
47impl ast::TypeParamsOwner for FnDef {} 25impl ast::TypeParamsOwner for FnDef {}
@@ -64,17 +42,6 @@ impl FnDef {
64pub struct RetType { 42pub struct RetType {
65 pub(crate) syntax: SyntaxNode, 43 pub(crate) syntax: SyntaxNode,
66} 44}
67impl 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}
78impl RetType { 45impl 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 {
84pub struct StructDef { 51pub struct StructDef {
85 pub(crate) syntax: SyntaxNode, 52 pub(crate) syntax: SyntaxNode,
86} 53}
87impl 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}
98impl ast::VisibilityOwner for StructDef {} 54impl ast::VisibilityOwner for StructDef {}
99impl ast::NameOwner for StructDef {} 55impl ast::NameOwner for StructDef {}
100impl ast::TypeParamsOwner for StructDef {} 56impl ast::TypeParamsOwner for StructDef {}
@@ -110,17 +66,6 @@ impl StructDef {
110pub struct UnionDef { 66pub struct UnionDef {
111 pub(crate) syntax: SyntaxNode, 67 pub(crate) syntax: SyntaxNode,
112} 68}
113impl 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}
124impl ast::VisibilityOwner for UnionDef {} 69impl ast::VisibilityOwner for UnionDef {}
125impl ast::NameOwner for UnionDef {} 70impl ast::NameOwner for UnionDef {}
126impl ast::TypeParamsOwner for UnionDef {} 71impl ast::TypeParamsOwner for UnionDef {}
@@ -137,17 +82,6 @@ impl UnionDef {
137pub struct RecordFieldDefList { 82pub struct RecordFieldDefList {
138 pub(crate) syntax: SyntaxNode, 83 pub(crate) syntax: SyntaxNode,
139} 84}
140impl 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}
151impl RecordFieldDefList { 85impl 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 {
158pub struct RecordFieldDef { 92pub struct RecordFieldDef {
159 pub(crate) syntax: SyntaxNode, 93 pub(crate) syntax: SyntaxNode,
160} 94}
161impl 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}
172impl ast::VisibilityOwner for RecordFieldDef {} 95impl ast::VisibilityOwner for RecordFieldDef {}
173impl ast::NameOwner for RecordFieldDef {} 96impl ast::NameOwner for RecordFieldDef {}
174impl ast::AttrsOwner for RecordFieldDef {} 97impl ast::AttrsOwner for RecordFieldDef {}
@@ -180,17 +103,6 @@ impl RecordFieldDef {}
180pub struct TupleFieldDefList { 103pub struct TupleFieldDefList {
181 pub(crate) syntax: SyntaxNode, 104 pub(crate) syntax: SyntaxNode,
182} 105}
183impl 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}
194impl TupleFieldDefList { 106impl 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 {
201pub struct TupleFieldDef { 113pub struct TupleFieldDef {
202 pub(crate) syntax: SyntaxNode, 114 pub(crate) syntax: SyntaxNode,
203} 115}
204impl 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}
215impl ast::VisibilityOwner for TupleFieldDef {} 116impl ast::VisibilityOwner for TupleFieldDef {}
216impl ast::AttrsOwner for TupleFieldDef {} 117impl ast::AttrsOwner for TupleFieldDef {}
217impl TupleFieldDef { 118impl TupleFieldDef {
@@ -222,17 +123,6 @@ impl TupleFieldDef {
222pub struct EnumDef { 123pub struct EnumDef {
223 pub(crate) syntax: SyntaxNode, 124 pub(crate) syntax: SyntaxNode,
224} 125}
225impl 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}
236impl ast::VisibilityOwner for EnumDef {} 126impl ast::VisibilityOwner for EnumDef {}
237impl ast::NameOwner for EnumDef {} 127impl ast::NameOwner for EnumDef {}
238impl ast::TypeParamsOwner for EnumDef {} 128impl ast::TypeParamsOwner for EnumDef {}
@@ -247,17 +137,6 @@ impl EnumDef {
247pub struct EnumVariantList { 137pub struct EnumVariantList {
248 pub(crate) syntax: SyntaxNode, 138 pub(crate) syntax: SyntaxNode,
249} 139}
250impl 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}
261impl EnumVariantList { 140impl 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 {
268pub struct EnumVariant { 147pub struct EnumVariant {
269 pub(crate) syntax: SyntaxNode, 148 pub(crate) syntax: SyntaxNode,
270} 149}
271impl 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}
282impl ast::VisibilityOwner for EnumVariant {} 150impl ast::VisibilityOwner for EnumVariant {}
283impl ast::NameOwner for EnumVariant {} 151impl ast::NameOwner for EnumVariant {}
284impl ast::DocCommentsOwner for EnumVariant {} 152impl ast::DocCommentsOwner for EnumVariant {}
@@ -293,17 +161,6 @@ impl EnumVariant {
293pub struct TraitDef { 161pub struct TraitDef {
294 pub(crate) syntax: SyntaxNode, 162 pub(crate) syntax: SyntaxNode,
295} 163}
296impl 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}
307impl ast::VisibilityOwner for TraitDef {} 164impl ast::VisibilityOwner for TraitDef {}
308impl ast::NameOwner for TraitDef {} 165impl ast::NameOwner for TraitDef {}
309impl ast::AttrsOwner for TraitDef {} 166impl ast::AttrsOwner for TraitDef {}
@@ -321,17 +178,6 @@ impl TraitDef {
321pub struct Module { 178pub struct Module {
322 pub(crate) syntax: SyntaxNode, 179 pub(crate) syntax: SyntaxNode,
323} 180}
324impl 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}
335impl ast::VisibilityOwner for Module {} 181impl ast::VisibilityOwner for Module {}
336impl ast::NameOwner for Module {} 182impl ast::NameOwner for Module {}
337impl ast::AttrsOwner for Module {} 183impl ast::AttrsOwner for Module {}
@@ -346,17 +192,6 @@ impl Module {
346pub struct ItemList { 192pub struct ItemList {
347 pub(crate) syntax: SyntaxNode, 193 pub(crate) syntax: SyntaxNode,
348} 194}
349impl 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}
360impl ast::ModuleItemOwner for ItemList {} 195impl ast::ModuleItemOwner for ItemList {}
361impl ItemList { 196impl 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 {
368pub struct ConstDef { 203pub struct ConstDef {
369 pub(crate) syntax: SyntaxNode, 204 pub(crate) syntax: SyntaxNode,
370} 205}
371impl 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}
382impl ast::VisibilityOwner for ConstDef {} 206impl ast::VisibilityOwner for ConstDef {}
383impl ast::NameOwner for ConstDef {} 207impl ast::NameOwner for ConstDef {}
384impl ast::TypeParamsOwner for ConstDef {} 208impl ast::TypeParamsOwner for ConstDef {}
@@ -397,17 +221,6 @@ impl ConstDef {
397pub struct StaticDef { 221pub struct StaticDef {
398 pub(crate) syntax: SyntaxNode, 222 pub(crate) syntax: SyntaxNode,
399} 223}
400impl 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}
411impl ast::VisibilityOwner for StaticDef {} 224impl ast::VisibilityOwner for StaticDef {}
412impl ast::NameOwner for StaticDef {} 225impl ast::NameOwner for StaticDef {}
413impl ast::TypeParamsOwner for StaticDef {} 226impl ast::TypeParamsOwner for StaticDef {}
@@ -426,17 +239,6 @@ impl StaticDef {
426pub struct TypeAliasDef { 239pub struct TypeAliasDef {
427 pub(crate) syntax: SyntaxNode, 240 pub(crate) syntax: SyntaxNode,
428} 241}
429impl 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}
440impl ast::VisibilityOwner for TypeAliasDef {} 242impl ast::VisibilityOwner for TypeAliasDef {}
441impl ast::NameOwner for TypeAliasDef {} 243impl ast::NameOwner for TypeAliasDef {}
442impl ast::TypeParamsOwner for TypeAliasDef {} 244impl ast::TypeParamsOwner for TypeAliasDef {}
@@ -455,17 +257,6 @@ impl TypeAliasDef {
455pub struct ImplDef { 257pub struct ImplDef {
456 pub(crate) syntax: SyntaxNode, 258 pub(crate) syntax: SyntaxNode,
457} 259}
458impl 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}
469impl ast::TypeParamsOwner for ImplDef {} 260impl ast::TypeParamsOwner for ImplDef {}
470impl ast::AttrsOwner for ImplDef {} 261impl ast::AttrsOwner for ImplDef {}
471impl ImplDef { 262impl ImplDef {
@@ -482,8 +273,1262 @@ impl ImplDef {
482pub struct ParenType { 273pub struct ParenType {
483 pub(crate) syntax: SyntaxNode, 274 pub(crate) syntax: SyntaxNode,
484} 275}
485impl AstNode for ParenType { 276impl 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)]
283pub struct TupleType {
284 pub(crate) syntax: SyntaxNode,
285}
286impl 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)]
293pub struct NeverType {
294 pub(crate) syntax: SyntaxNode,
295}
296impl NeverType {
297 pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
298}
299
300#[derive(Debug, Clone, PartialEq, Eq, Hash)]
301pub struct PathType {
302 pub(crate) syntax: SyntaxNode,
303}
304impl PathType {
305 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
306}
307
308#[derive(Debug, Clone, PartialEq, Eq, Hash)]
309pub struct PointerType {
310 pub(crate) syntax: SyntaxNode,
311}
312impl 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)]
320pub struct ArrayType {
321 pub(crate) syntax: SyntaxNode,
322}
323impl 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)]
332pub struct SliceType {
333 pub(crate) syntax: SyntaxNode,
334}
335impl 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)]
342pub struct ReferenceType {
343 pub(crate) syntax: SyntaxNode,
344}
345impl 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)]
355pub struct PlaceholderType {
356 pub(crate) syntax: SyntaxNode,
357}
358impl PlaceholderType {
359 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
360}
361
362#[derive(Debug, Clone, PartialEq, Eq, Hash)]
363pub struct FnPointerType {
364 pub(crate) syntax: SyntaxNode,
365}
366impl 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)]
375pub struct ForType {
376 pub(crate) syntax: SyntaxNode,
377}
378impl 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)]
385pub struct ImplTraitType {
386 pub(crate) syntax: SyntaxNode,
387}
388impl ast::TypeBoundsOwner for ImplTraitType {}
389impl ImplTraitType {
390 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
391}
392
393#[derive(Debug, Clone, PartialEq, Eq, Hash)]
394pub struct DynTraitType {
395 pub(crate) syntax: SyntaxNode,
396}
397impl ast::TypeBoundsOwner for DynTraitType {}
398impl DynTraitType {
399 pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
400}
401
402#[derive(Debug, Clone, PartialEq, Eq, Hash)]
403pub struct TupleExpr {
404 pub(crate) syntax: SyntaxNode,
405}
406impl ast::AttrsOwner for TupleExpr {}
407impl 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)]
414pub struct ArrayExpr {
415 pub(crate) syntax: SyntaxNode,
416}
417impl ast::AttrsOwner for ArrayExpr {}
418impl 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)]
426pub struct ParenExpr {
427 pub(crate) syntax: SyntaxNode,
428}
429impl ast::AttrsOwner for ParenExpr {}
430impl 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)]
437pub struct PathExpr {
438 pub(crate) syntax: SyntaxNode,
439}
440impl PathExpr {
441 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
442}
443
444#[derive(Debug, Clone, PartialEq, Eq, Hash)]
445pub struct LambdaExpr {
446 pub(crate) syntax: SyntaxNode,
447}
448impl ast::AttrsOwner for LambdaExpr {}
449impl 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)]
459pub struct IfExpr {
460 pub(crate) syntax: SyntaxNode,
461}
462impl ast::AttrsOwner for IfExpr {}
463impl 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)]
469pub struct LoopExpr {
470 pub(crate) syntax: SyntaxNode,
471}
472impl ast::AttrsOwner for LoopExpr {}
473impl ast::LoopBodyOwner for LoopExpr {}
474impl LoopExpr {
475 pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
476}
477
478#[derive(Debug, Clone, PartialEq, Eq, Hash)]
479pub struct TryBlockExpr {
480 pub(crate) syntax: SyntaxNode,
481}
482impl ast::AttrsOwner for TryBlockExpr {}
483impl 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)]
489pub struct ForExpr {
490 pub(crate) syntax: SyntaxNode,
491}
492impl ast::AttrsOwner for ForExpr {}
493impl ast::LoopBodyOwner for ForExpr {}
494impl 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)]
502pub struct WhileExpr {
503 pub(crate) syntax: SyntaxNode,
504}
505impl ast::AttrsOwner for WhileExpr {}
506impl ast::LoopBodyOwner for WhileExpr {}
507impl 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)]
513pub struct ContinueExpr {
514 pub(crate) syntax: SyntaxNode,
515}
516impl ast::AttrsOwner for ContinueExpr {}
517impl 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)]
527pub struct BreakExpr {
528 pub(crate) syntax: SyntaxNode,
529}
530impl ast::AttrsOwner for BreakExpr {}
531impl 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)]
540pub struct Label {
541 pub(crate) syntax: SyntaxNode,
542}
543impl 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)]
550pub struct BlockExpr {
551 pub(crate) syntax: SyntaxNode,
552}
553impl ast::AttrsOwner for BlockExpr {}
554impl 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)]
561pub struct ReturnExpr {
562 pub(crate) syntax: SyntaxNode,
563}
564impl ast::AttrsOwner for ReturnExpr {}
565impl ReturnExpr {
566 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
567}
568
569#[derive(Debug, Clone, PartialEq, Eq, Hash)]
570pub struct CallExpr {
571 pub(crate) syntax: SyntaxNode,
572}
573impl ast::ArgListOwner for CallExpr {}
574impl CallExpr {
575 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
576}
577
578#[derive(Debug, Clone, PartialEq, Eq, Hash)]
579pub struct MethodCallExpr {
580 pub(crate) syntax: SyntaxNode,
581}
582impl ast::AttrsOwner for MethodCallExpr {}
583impl ast::ArgListOwner for MethodCallExpr {}
584impl 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)]
592pub struct IndexExpr {
593 pub(crate) syntax: SyntaxNode,
594}
595impl ast::AttrsOwner for IndexExpr {}
596impl 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)]
602pub struct FieldExpr {
603 pub(crate) syntax: SyntaxNode,
604}
605impl ast::AttrsOwner for FieldExpr {}
606impl 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)]
613pub struct AwaitExpr {
614 pub(crate) syntax: SyntaxNode,
615}
616impl ast::AttrsOwner for AwaitExpr {}
617impl 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)]
624pub struct TryExpr {
625 pub(crate) syntax: SyntaxNode,
626}
627impl ast::AttrsOwner for TryExpr {}
628impl 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)]
634pub struct CastExpr {
635 pub(crate) syntax: SyntaxNode,
636}
637impl ast::AttrsOwner for CastExpr {}
638impl 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)]
645pub struct RefExpr {
646 pub(crate) syntax: SyntaxNode,
647}
648impl ast::AttrsOwner for RefExpr {}
649impl 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)]
657pub struct PrefixExpr {
658 pub(crate) syntax: SyntaxNode,
659}
660impl ast::AttrsOwner for PrefixExpr {}
661impl PrefixExpr {
662 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
663}
664
665#[derive(Debug, Clone, PartialEq, Eq, Hash)]
666pub struct BoxExpr {
667 pub(crate) syntax: SyntaxNode,
668}
669impl ast::AttrsOwner for BoxExpr {}
670impl 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)]
676pub struct RangeExpr {
677 pub(crate) syntax: SyntaxNode,
678}
679impl ast::AttrsOwner for RangeExpr {}
680impl RangeExpr {}
681
682#[derive(Debug, Clone, PartialEq, Eq, Hash)]
683pub struct BinExpr {
684 pub(crate) syntax: SyntaxNode,
685}
686impl ast::AttrsOwner for BinExpr {}
687impl BinExpr {}
688
689#[derive(Debug, Clone, PartialEq, Eq, Hash)]
690pub struct Literal {
691 pub(crate) syntax: SyntaxNode,
692}
693impl Literal {}
694
695#[derive(Debug, Clone, PartialEq, Eq, Hash)]
696pub struct MatchExpr {
697 pub(crate) syntax: SyntaxNode,
698}
699impl ast::AttrsOwner for MatchExpr {}
700impl 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)]
707pub struct MatchArmList {
708 pub(crate) syntax: SyntaxNode,
709}
710impl ast::AttrsOwner for MatchArmList {}
711impl 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)]
718pub struct MatchArm {
719 pub(crate) syntax: SyntaxNode,
720}
721impl ast::AttrsOwner for MatchArm {}
722impl 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)]
730pub struct MatchGuard {
731 pub(crate) syntax: SyntaxNode,
732}
733impl 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)]
739pub struct RecordLit {
740 pub(crate) syntax: SyntaxNode,
741}
742impl 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)]
748pub struct RecordFieldList {
749 pub(crate) syntax: SyntaxNode,
750}
751impl 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)]
760pub struct RecordField {
761 pub(crate) syntax: SyntaxNode,
762}
763impl ast::AttrsOwner for RecordField {}
764impl 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)]
771pub struct OrPat {
772 pub(crate) syntax: SyntaxNode,
773}
774impl OrPat {
775 pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
776}
777
778#[derive(Debug, Clone, PartialEq, Eq, Hash)]
779pub struct ParenPat {
780 pub(crate) syntax: SyntaxNode,
781}
782impl 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)]
789pub struct RefPat {
790 pub(crate) syntax: SyntaxNode,
791}
792impl 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)]
799pub struct BoxPat {
800 pub(crate) syntax: SyntaxNode,
801}
802impl 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)]
808pub struct BindPat {
809 pub(crate) syntax: SyntaxNode,
810}
811impl ast::AttrsOwner for BindPat {}
812impl ast::NameOwner for BindPat {}
813impl 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)]
821pub struct PlaceholderPat {
822 pub(crate) syntax: SyntaxNode,
823}
824impl PlaceholderPat {
825 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
826}
827
828#[derive(Debug, Clone, PartialEq, Eq, Hash)]
829pub struct DotDotPat {
830 pub(crate) syntax: SyntaxNode,
831}
832impl DotDotPat {
833 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
834}
835
836#[derive(Debug, Clone, PartialEq, Eq, Hash)]
837pub struct PathPat {
838 pub(crate) syntax: SyntaxNode,
839}
840impl PathPat {
841 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
842}
843
844#[derive(Debug, Clone, PartialEq, Eq, Hash)]
845pub struct SlicePat {
846 pub(crate) syntax: SyntaxNode,
847}
848impl 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)]
855pub struct RangePat {
856 pub(crate) syntax: SyntaxNode,
857}
858impl RangePat {}
859
860#[derive(Debug, Clone, PartialEq, Eq, Hash)]
861pub struct LiteralPat {
862 pub(crate) syntax: SyntaxNode,
863}
864impl LiteralPat {
865 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
866}
867
868#[derive(Debug, Clone, PartialEq, Eq, Hash)]
869pub struct MacroPat {
870 pub(crate) syntax: SyntaxNode,
871}
872impl MacroPat {
873 pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
874}
875
876#[derive(Debug, Clone, PartialEq, Eq, Hash)]
877pub struct RecordPat {
878 pub(crate) syntax: SyntaxNode,
879}
880impl 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)]
888pub struct RecordFieldPatList {
889 pub(crate) syntax: SyntaxNode,
890}
891impl 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)]
903pub struct RecordFieldPat {
904 pub(crate) syntax: SyntaxNode,
905}
906impl ast::AttrsOwner for RecordFieldPat {}
907impl 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)]
914pub struct TupleStructPat {
915 pub(crate) syntax: SyntaxNode,
916}
917impl 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)]
925pub struct TuplePat {
926 pub(crate) syntax: SyntaxNode,
927}
928impl 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)]
935pub struct Visibility {
936 pub(crate) syntax: SyntaxNode,
937}
938impl 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)]
946pub struct Name {
947 pub(crate) syntax: SyntaxNode,
948}
949impl Name {
950 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
951}
952
953#[derive(Debug, Clone, PartialEq, Eq, Hash)]
954pub struct NameRef {
955 pub(crate) syntax: SyntaxNode,
956}
957impl NameRef {}
958
959#[derive(Debug, Clone, PartialEq, Eq, Hash)]
960pub struct MacroCall {
961 pub(crate) syntax: SyntaxNode,
962}
963impl ast::NameOwner for MacroCall {}
964impl ast::AttrsOwner for MacroCall {}
965impl ast::DocCommentsOwner for MacroCall {}
966impl 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)]
974pub struct Attr {
975 pub(crate) syntax: SyntaxNode,
976}
977impl 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)]
988pub struct TokenTree {
989 pub(crate) syntax: SyntaxNode,
990}
991impl TokenTree {}
992
993#[derive(Debug, Clone, PartialEq, Eq, Hash)]
994pub struct TypeParamList {
995 pub(crate) syntax: SyntaxNode,
996}
997impl 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)]
1007pub struct TypeParam {
1008 pub(crate) syntax: SyntaxNode,
1009}
1010impl ast::NameOwner for TypeParam {}
1011impl ast::AttrsOwner for TypeParam {}
1012impl ast::TypeBoundsOwner for TypeParam {}
1013impl 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)]
1019pub struct ConstParam {
1020 pub(crate) syntax: SyntaxNode,
1021}
1022impl ast::NameOwner for ConstParam {}
1023impl ast::AttrsOwner for ConstParam {}
1024impl ast::TypeAscriptionOwner for ConstParam {}
1025impl 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)]
1031pub struct LifetimeParam {
1032 pub(crate) syntax: SyntaxNode,
1033}
1034impl ast::AttrsOwner for LifetimeParam {}
1035impl 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)]
1042pub struct TypeBound {
1043 pub(crate) syntax: SyntaxNode,
1044}
1045impl 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)]
1054pub struct TypeBoundList {
1055 pub(crate) syntax: SyntaxNode,
1056}
1057impl TypeBoundList {
1058 pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
1059}
1060
1061#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1062pub struct WherePred {
1063 pub(crate) syntax: SyntaxNode,
1064}
1065impl ast::TypeBoundsOwner for WherePred {}
1066impl 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)]
1074pub struct WhereClause {
1075 pub(crate) syntax: SyntaxNode,
1076}
1077impl 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)]
1083pub struct Abi {
1084 pub(crate) syntax: SyntaxNode,
1085}
1086impl Abi {}
1087
1088#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1089pub struct ExprStmt {
1090 pub(crate) syntax: SyntaxNode,
1091}
1092impl ast::AttrsOwner for ExprStmt {}
1093impl 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)]
1099pub struct LetStmt {
1100 pub(crate) syntax: SyntaxNode,
1101}
1102impl ast::AttrsOwner for LetStmt {}
1103impl ast::TypeAscriptionOwner for LetStmt {}
1104impl 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)]
1113pub struct Condition {
1114 pub(crate) syntax: SyntaxNode,
1115}
1116impl 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)]
1124pub struct Block {
1125 pub(crate) syntax: SyntaxNode,
1126}
1127impl ast::AttrsOwner for Block {}
1128impl ast::ModuleItemOwner for Block {}
1129impl 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)]
1137pub struct ParamList {
1138 pub(crate) syntax: SyntaxNode,
1139}
1140impl 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)]
1148pub struct SelfParam {
1149 pub(crate) syntax: SyntaxNode,
1150}
1151impl ast::TypeAscriptionOwner for SelfParam {}
1152impl ast::AttrsOwner for SelfParam {}
1153impl 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)]
1163pub struct Param {
1164 pub(crate) syntax: SyntaxNode,
1165}
1166impl ast::TypeAscriptionOwner for Param {}
1167impl ast::AttrsOwner for Param {}
1168impl 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)]
1174pub struct UseItem {
1175 pub(crate) syntax: SyntaxNode,
1176}
1177impl ast::AttrsOwner for UseItem {}
1178impl ast::VisibilityOwner for UseItem {}
1179impl 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)]
1185pub struct UseTree {
1186 pub(crate) syntax: SyntaxNode,
1187}
1188impl 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)]
1196pub struct Alias {
1197 pub(crate) syntax: SyntaxNode,
1198}
1199impl ast::NameOwner for Alias {}
1200impl Alias {
1201 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
1202}
1203
1204#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1205pub struct UseTreeList {
1206 pub(crate) syntax: SyntaxNode,
1207}
1208impl 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)]
1215pub struct ExternCrateItem {
1216 pub(crate) syntax: SyntaxNode,
1217}
1218impl ast::AttrsOwner for ExternCrateItem {}
1219impl ast::VisibilityOwner for ExternCrateItem {}
1220impl 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)]
1228pub struct ArgList {
1229 pub(crate) syntax: SyntaxNode,
1230}
1231impl 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)]
1238pub struct Path {
1239 pub(crate) syntax: SyntaxNode,
1240}
1241impl 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)]
1247pub struct PathSegment {
1248 pub(crate) syntax: SyntaxNode,
1249}
1250impl 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)]
1262pub struct TypeArgList {
1263 pub(crate) syntax: SyntaxNode,
1264}
1265impl 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)]
1277pub struct TypeArg {
1278 pub(crate) syntax: SyntaxNode,
1279}
1280impl TypeArg {
1281 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
1282}
1283
1284#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1285pub struct AssocTypeArg {
1286 pub(crate) syntax: SyntaxNode,
1287}
1288impl ast::TypeBoundsOwner for AssocTypeArg {}
1289impl 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)]
1296pub struct LifetimeArg {
1297 pub(crate) syntax: SyntaxNode,
1298}
1299impl 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)]
1306pub struct ConstArg {
1307 pub(crate) syntax: SyntaxNode,
1308}
1309impl 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)]
1316pub struct MacroItems {
1317 pub(crate) syntax: SyntaxNode,
1318}
1319impl ast::ModuleItemOwner for MacroItems {}
1320impl MacroItems {}
1321
1322#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1323pub struct MacroStmts {
1324 pub(crate) syntax: SyntaxNode,
1325}
1326impl 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)]
1332pub struct ExternItemList {
1333 pub(crate) syntax: SyntaxNode,
1334}
1335impl ast::ModuleItemOwner for ExternItemList {}
1336impl 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)]
1343pub struct ExternBlock {
1344 pub(crate) syntax: SyntaxNode,
1345}
1346impl 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)]
1352pub struct MetaItem {
1353 pub(crate) syntax: SyntaxNode,
1354}
1355impl 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)]
1363pub struct MacroDef {
1364 pub(crate) syntax: SyntaxNode,
1365}
1366impl 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)]
1372pub enum NominalDef {
1373 StructDef(StructDef),
1374 EnumDef(EnumDef),
1375 UnionDef(UnionDef),
1376}
1377impl ast::NameOwner for NominalDef {}
1378impl ast::TypeParamsOwner for NominalDef {}
1379impl ast::AttrsOwner for NominalDef {}
1380
1381#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1382pub enum GenericParam {
1383 LifetimeParam(LifetimeParam),
1384 TypeParam(TypeParam),
1385 ConstParam(ConstParam),
1386}
1387
1388#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1389pub enum GenericArg {
1390 LifetimeArg(LifetimeArg),
1391 TypeArg(TypeArg),
1392 ConstArg(ConstArg),
1393 AssocTypeArg(AssocTypeArg),
1394}
1395
1396#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1397pub 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)]
1414pub 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}
1430impl ast::NameOwner for ModuleItem {}
1431impl ast::AttrsOwner for ModuleItem {}
1432impl ast::VisibilityOwner for ModuleItem {}
1433
1434#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1435pub enum ImplItem {
1436 FnDef(FnDef),
1437 TypeAliasDef(TypeAliasDef),
1438 ConstDef(ConstDef),
1439}
1440impl ast::NameOwner for ImplItem {}
1441impl ast::AttrsOwner for ImplItem {}
1442
1443#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1444pub enum ExternItem {
1445 FnDef(FnDef),
1446 StaticDef(StaticDef),
1447}
1448impl ast::NameOwner for ExternItem {}
1449impl ast::AttrsOwner for ExternItem {}
1450impl ast::VisibilityOwner for ExternItem {}
1451
1452#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1453pub 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}
1486impl ast::AttrsOwner for Expr {}
1487
1488#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1489pub 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)]
1508pub enum RecordInnerPat {
1509 RecordFieldPat(RecordFieldPat),
1510 BindPat(BindPat),
1511}
1512
1513#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1514pub enum AttrInput {
1515 Literal(Literal),
1516 TokenTree(TokenTree),
1517}
1518
1519#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1520pub enum Stmt {
1521 LetStmt(LetStmt),
1522 ExprStmt(ExprStmt),
1523}
1524
1525#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1526pub enum FieldDefList {
1527 RecordFieldDefList(RecordFieldDefList),
1528 TupleFieldDefList(TupleFieldDefList),
1529}
1530impl 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}
496impl ParenType { 1541impl 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 1552impl AstNode for RetType {
502#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1553 fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE }
503pub 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}
506impl AstNode for TupleType { 1563impl 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}
517impl TupleType { 1574impl 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 1585impl AstNode for RecordFieldDefList {
523#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1586 fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_DEF_LIST }
524pub 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}
527impl AstNode for NeverType { 1596impl 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}
538impl NeverType { 1607impl 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 1618impl AstNode for TupleFieldDef {
542#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1619 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_DEF }
543pub 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}
546impl AstNode for PathType { 1629impl 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}
557impl PathType { 1640impl 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 1651impl AstNode for EnumVariant {
561#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1652 fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM_VARIANT }
562pub 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}
565impl AstNode for PointerType { 1662impl 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}
576impl PointerType { 1673impl 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 1684impl AstNode for ItemList {
583#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1685 fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST }
584pub 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}
587impl AstNode for ArrayType { 1695impl 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}
598impl ArrayType { 1706impl 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 1717impl AstNode for TypeAliasDef {
606#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1718 fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS_DEF }
607pub 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}
610impl AstNode for SliceType { 1728impl 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}
621impl SliceType { 1739impl 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 1750impl AstNode for TupleType {
627#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1751 fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE }
628pub 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}
631impl AstNode for ReferenceType { 1761impl 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}
642impl ReferenceType { 1772impl 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 1783impl AstNode for PointerType {
651#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1784 fn can_cast(kind: SyntaxKind) -> bool { kind == POINTER_TYPE }
652pub 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}
655impl AstNode for PlaceholderType { 1794impl 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}
666impl PlaceholderType { 1805impl 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 1816impl AstNode for ReferenceType {
670#[derive(Debug, Clone, PartialEq, Eq, Hash)] 1817 fn can_cast(kind: SyntaxKind) -> bool { kind == REFERENCE_TYPE }
671pub 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}
1827impl 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}
674impl AstNode for FnPointerType { 1838impl 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}
685impl 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)]
694pub struct ForType {
695 pub(crate) syntax: SyntaxNode,
696}
697impl AstNode for ForType { 1849impl 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}
708impl 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)]
715pub struct ImplTraitType {
716 pub(crate) syntax: SyntaxNode,
717}
718impl AstNode for ImplTraitType { 1860impl 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}
729impl ast::TypeBoundsOwner for ImplTraitType {}
730impl ImplTraitType {
731 pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
732}
733
734#[derive(Debug, Clone, PartialEq, Eq, Hash)]
735pub struct DynTraitType {
736 pub(crate) syntax: SyntaxNode,
737}
738impl AstNode for DynTraitType { 1871impl 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}
749impl ast::TypeBoundsOwner for DynTraitType {}
750impl DynTraitType {
751 pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
752}
753
754#[derive(Debug, Clone, PartialEq, Eq, Hash)]
755pub struct TupleExpr {
756 pub(crate) syntax: SyntaxNode,
757}
758impl AstNode for TupleExpr { 1882impl 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}
769impl ast::AttrsOwner for TupleExpr {}
770impl 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)]
777pub struct ArrayExpr {
778 pub(crate) syntax: SyntaxNode,
779}
780impl AstNode for ArrayExpr { 1893impl 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}
791impl ast::AttrsOwner for ArrayExpr {}
792impl 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)]
800pub struct ParenExpr {
801 pub(crate) syntax: SyntaxNode,
802}
803impl AstNode for ParenExpr { 1904impl 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}
814impl ast::AttrsOwner for ParenExpr {}
815impl 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)]
822pub struct PathExpr {
823 pub(crate) syntax: SyntaxNode,
824}
825impl AstNode for PathExpr { 1915impl 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}
836impl PathExpr {
837 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
838}
839
840#[derive(Debug, Clone, PartialEq, Eq, Hash)]
841pub struct LambdaExpr {
842 pub(crate) syntax: SyntaxNode,
843}
844impl AstNode for LambdaExpr { 1926impl 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}
855impl ast::AttrsOwner for LambdaExpr {}
856impl 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)]
866pub struct IfExpr {
867 pub(crate) syntax: SyntaxNode,
868}
869impl AstNode for IfExpr { 1937impl 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}
880impl ast::AttrsOwner for IfExpr {}
881impl 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)]
887pub struct LoopExpr {
888 pub(crate) syntax: SyntaxNode,
889}
890impl AstNode for LoopExpr { 1948impl 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}
901impl ast::AttrsOwner for LoopExpr {}
902impl ast::LoopBodyOwner for LoopExpr {}
903impl LoopExpr {
904 pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
905}
906
907#[derive(Debug, Clone, PartialEq, Eq, Hash)]
908pub struct TryBlockExpr {
909 pub(crate) syntax: SyntaxNode,
910}
911impl AstNode for TryBlockExpr { 1959impl 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}
922impl ast::AttrsOwner for TryBlockExpr {}
923impl 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)]
929pub struct ForExpr {
930 pub(crate) syntax: SyntaxNode,
931}
932impl AstNode for ForExpr { 1970impl 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}
943impl ast::AttrsOwner for ForExpr {}
944impl ast::LoopBodyOwner for ForExpr {}
945impl 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)]
953pub struct WhileExpr {
954 pub(crate) syntax: SyntaxNode,
955}
956impl AstNode for WhileExpr { 1981impl 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}
967impl ast::AttrsOwner for WhileExpr {}
968impl ast::LoopBodyOwner for WhileExpr {}
969impl 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)]
975pub struct ContinueExpr {
976 pub(crate) syntax: SyntaxNode,
977}
978impl AstNode for ContinueExpr { 1992impl 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}
989impl ast::AttrsOwner for ContinueExpr {}
990impl 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)]
1000pub struct BreakExpr {
1001 pub(crate) syntax: SyntaxNode,
1002}
1003impl AstNode for BreakExpr { 2003impl 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}
1014impl ast::AttrsOwner for BreakExpr {}
1015impl 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)]
1024pub struct Label {
1025 pub(crate) syntax: SyntaxNode,
1026}
1027impl AstNode for Label { 2014impl 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}
1038impl 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)]
1045pub struct BlockExpr {
1046 pub(crate) syntax: SyntaxNode,
1047}
1048impl AstNode for BlockExpr { 2025impl 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}
1059impl ast::AttrsOwner for BlockExpr {}
1060impl 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)]
1067pub struct ReturnExpr {
1068 pub(crate) syntax: SyntaxNode,
1069}
1070impl AstNode for ReturnExpr { 2036impl 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}
1081impl ast::AttrsOwner for ReturnExpr {}
1082impl ReturnExpr {
1083 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
1084}
1085
1086#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1087pub struct CallExpr {
1088 pub(crate) syntax: SyntaxNode,
1089}
1090impl AstNode for CallExpr { 2047impl 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}
1101impl ast::ArgListOwner for CallExpr {}
1102impl CallExpr {
1103 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
1104}
1105
1106#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1107pub struct MethodCallExpr {
1108 pub(crate) syntax: SyntaxNode,
1109}
1110impl AstNode for MethodCallExpr { 2058impl 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}
1121impl ast::AttrsOwner for MethodCallExpr {}
1122impl ast::ArgListOwner for MethodCallExpr {}
1123impl 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)]
1131pub struct IndexExpr {
1132 pub(crate) syntax: SyntaxNode,
1133}
1134impl AstNode for IndexExpr { 2069impl 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}
1145impl ast::AttrsOwner for IndexExpr {}
1146impl 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)]
1152pub struct FieldExpr {
1153 pub(crate) syntax: SyntaxNode,
1154}
1155impl AstNode for FieldExpr { 2080impl 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}
1166impl ast::AttrsOwner for FieldExpr {}
1167impl 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)]
1174pub struct AwaitExpr {
1175 pub(crate) syntax: SyntaxNode,
1176}
1177impl AstNode for AwaitExpr { 2091impl 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}
1188impl ast::AttrsOwner for AwaitExpr {}
1189impl 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)]
1196pub struct TryExpr {
1197 pub(crate) syntax: SyntaxNode,
1198}
1199impl AstNode for TryExpr { 2102impl 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}
1210impl ast::AttrsOwner for TryExpr {}
1211impl 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)]
1217pub struct CastExpr {
1218 pub(crate) syntax: SyntaxNode,
1219}
1220impl AstNode for CastExpr { 2113impl 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}
1231impl ast::AttrsOwner for CastExpr {}
1232impl 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)]
1239pub struct RefExpr {
1240 pub(crate) syntax: SyntaxNode,
1241}
1242impl AstNode for RefExpr { 2124impl 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}
1253impl ast::AttrsOwner for RefExpr {}
1254impl 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)]
1262pub struct PrefixExpr {
1263 pub(crate) syntax: SyntaxNode,
1264}
1265impl AstNode for PrefixExpr { 2135impl 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}
1276impl ast::AttrsOwner for PrefixExpr {}
1277impl PrefixExpr {
1278 pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
1279}
1280
1281#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1282pub struct BoxExpr {
1283 pub(crate) syntax: SyntaxNode,
1284}
1285impl AstNode for BoxExpr { 2146impl 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}
1296impl ast::AttrsOwner for BoxExpr {}
1297impl 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)]
1303pub struct RangeExpr {
1304 pub(crate) syntax: SyntaxNode,
1305}
1306impl AstNode for RangeExpr { 2157impl 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}
1317impl ast::AttrsOwner for RangeExpr {}
1318impl RangeExpr {}
1319
1320#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1321pub struct BinExpr {
1322 pub(crate) syntax: SyntaxNode,
1323}
1324impl AstNode for BinExpr { 2168impl 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}
1335impl ast::AttrsOwner for BinExpr {}
1336impl BinExpr {}
1337
1338#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1339pub struct Literal {
1340 pub(crate) syntax: SyntaxNode,
1341}
1342impl AstNode for Literal { 2179impl 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}
1353impl Literal {}
1354
1355#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1356pub struct MatchExpr {
1357 pub(crate) syntax: SyntaxNode,
1358}
1359impl AstNode for MatchExpr { 2190impl 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}
1370impl ast::AttrsOwner for MatchExpr {}
1371impl 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)]
1378pub struct MatchArmList {
1379 pub(crate) syntax: SyntaxNode,
1380}
1381impl AstNode for MatchArmList { 2201impl 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}
1392impl ast::AttrsOwner for MatchArmList {}
1393impl 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)]
1400pub struct MatchArm {
1401 pub(crate) syntax: SyntaxNode,
1402}
1403impl AstNode for MatchArm { 2212impl 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}
1414impl ast::AttrsOwner for MatchArm {}
1415impl 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)]
1423pub struct MatchGuard {
1424 pub(crate) syntax: SyntaxNode,
1425}
1426impl AstNode for MatchGuard { 2223impl 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}
1437impl 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)]
1443pub struct RecordLit {
1444 pub(crate) syntax: SyntaxNode,
1445}
1446impl AstNode for RecordLit { 2234impl 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}
1457impl 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)]
1463pub struct RecordFieldList {
1464 pub(crate) syntax: SyntaxNode,
1465}
1466impl AstNode for RecordFieldList { 2245impl 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}
1477impl 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)]
1486pub struct RecordField {
1487 pub(crate) syntax: SyntaxNode,
1488}
1489impl AstNode for RecordField { 2256impl 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}
1500impl ast::AttrsOwner for RecordField {}
1501impl 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)]
1508pub struct OrPat {
1509 pub(crate) syntax: SyntaxNode,
1510}
1511impl AstNode for OrPat { 2267impl 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}
1522impl OrPat {
1523 pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
1524}
1525
1526#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1527pub struct ParenPat {
1528 pub(crate) syntax: SyntaxNode,
1529}
1530impl AstNode for ParenPat { 2278impl 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}
1541impl 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)]
1548pub struct RefPat {
1549 pub(crate) syntax: SyntaxNode,
1550}
1551impl AstNode for RefPat { 2289impl 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}
1562impl 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)]
1569pub struct BoxPat {
1570 pub(crate) syntax: SyntaxNode,
1571}
1572impl AstNode for BoxPat { 2300impl 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}
1583impl 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)]
1589pub struct BindPat {
1590 pub(crate) syntax: SyntaxNode,
1591}
1592impl AstNode for BindPat { 2311impl 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}
1603impl ast::AttrsOwner for BindPat {}
1604impl ast::NameOwner for BindPat {}
1605impl 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)]
1613pub struct PlaceholderPat {
1614 pub(crate) syntax: SyntaxNode,
1615}
1616impl AstNode for PlaceholderPat { 2322impl 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}
1627impl PlaceholderPat {
1628 pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
1629}
1630
1631#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1632pub struct DotDotPat {
1633 pub(crate) syntax: SyntaxNode,
1634}
1635impl AstNode for DotDotPat { 2333impl 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}
1646impl DotDotPat {
1647 pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
1648}
1649
1650#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1651pub struct PathPat {
1652 pub(crate) syntax: SyntaxNode,
1653}
1654impl AstNode for PathPat { 2344impl 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}
1665impl PathPat {
1666 pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
1667}
1668
1669#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1670pub struct SlicePat {
1671 pub(crate) syntax: SyntaxNode,
1672}
1673impl AstNode for SlicePat { 2355impl 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}
1684impl 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)]
1691pub struct RangePat {
1692 pub(crate) syntax: SyntaxNode,
1693}
1694impl AstNode for RangePat { 2366impl 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}
1705impl RangePat {}
1706
1707#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1708pub struct LiteralPat {
1709 pub(crate) syntax: SyntaxNode,
1710}
1711impl AstNode for LiteralPat { 2377impl 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}
1722impl LiteralPat {
1723 pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
1724}
1725
1726#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1727pub struct MacroPat {
1728 pub(crate) syntax: SyntaxNode,
1729}
1730impl AstNode for MacroPat { 2388impl 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}
1741impl MacroPat {
1742 pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
1743}
1744
1745#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1746pub struct RecordPat {
1747 pub(crate) syntax: SyntaxNode,
1748}
1749impl AstNode for RecordPat { 2399impl 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}
1760impl 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)]
1768pub struct RecordFieldPatList {
1769 pub(crate) syntax: SyntaxNode,
1770}
1771impl AstNode for RecordFieldPatList { 2410impl 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}
1782impl 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)]
1794pub struct RecordFieldPat {
1795 pub(crate) syntax: SyntaxNode,
1796}
1797impl AstNode for RecordFieldPat { 2421impl 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}
1808impl ast::AttrsOwner for RecordFieldPat {}
1809impl 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)]
1816pub struct TupleStructPat {
1817 pub(crate) syntax: SyntaxNode,
1818}
1819impl AstNode for TupleStructPat { 2432impl 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}
1830impl 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)]
1838pub struct TuplePat {
1839 pub(crate) syntax: SyntaxNode,
1840}
1841impl AstNode for TuplePat { 2443impl 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}
1852impl 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)]
1859pub struct Visibility {
1860 pub(crate) syntax: SyntaxNode,
1861}
1862impl AstNode for Visibility { 2454impl 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}
1873impl 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)]
1881pub struct Name {
1882 pub(crate) syntax: SyntaxNode,
1883}
1884impl AstNode for Name { 2465impl 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}
1895impl Name {
1896 pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
1897}
1898
1899#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1900pub struct NameRef {
1901 pub(crate) syntax: SyntaxNode,
1902}
1903impl AstNode for NameRef { 2476impl 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}
1914impl NameRef {}
1915
1916#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1917pub struct MacroCall {
1918 pub(crate) syntax: SyntaxNode,
1919}
1920impl AstNode for MacroCall { 2487impl 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}
1931impl ast::NameOwner for MacroCall {}
1932impl ast::AttrsOwner for MacroCall {}
1933impl ast::DocCommentsOwner for MacroCall {}
1934impl 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)]
1942pub struct Attr {
1943 pub(crate) syntax: SyntaxNode,
1944}
1945impl AstNode for Attr { 2498impl 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}
1956impl 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)]
1967pub struct TokenTree {
1968 pub(crate) syntax: SyntaxNode,
1969}
1970impl AstNode for TokenTree { 2509impl 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}
1981impl TokenTree {}
1982
1983#[derive(Debug, Clone, PartialEq, Eq, Hash)]
1984pub struct TypeParamList {
1985 pub(crate) syntax: SyntaxNode,
1986}
1987impl AstNode for TypeParamList { 2520impl 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}
1998impl 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)]
2008pub struct TypeParam {
2009 pub(crate) syntax: SyntaxNode,
2010}
2011impl AstNode for TypeParam { 2531impl 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}
2022impl ast::NameOwner for TypeParam {}
2023impl ast::AttrsOwner for TypeParam {}
2024impl ast::TypeBoundsOwner for TypeParam {}
2025impl 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)]
2031pub struct ConstParam {
2032 pub(crate) syntax: SyntaxNode,
2033}
2034impl AstNode for ConstParam { 2542impl 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}
2045impl ast::NameOwner for ConstParam {}
2046impl ast::AttrsOwner for ConstParam {}
2047impl ast::TypeAscriptionOwner for ConstParam {}
2048impl 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)]
2054pub struct LifetimeParam {
2055 pub(crate) syntax: SyntaxNode,
2056}
2057impl AstNode for LifetimeParam { 2553impl 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}
2068impl ast::AttrsOwner for LifetimeParam {}
2069impl 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)]
2076pub struct TypeBound {
2077 pub(crate) syntax: SyntaxNode,
2078}
2079impl AstNode for TypeBound { 2564impl 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}
2090impl 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)]
2099pub struct TypeBoundList {
2100 pub(crate) syntax: SyntaxNode,
2101}
2102impl AstNode for TypeBoundList { 2575impl 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}
2113impl TypeBoundList {
2114 pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
2115}
2116
2117#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2118pub struct WherePred {
2119 pub(crate) syntax: SyntaxNode,
2120}
2121impl AstNode for WherePred { 2586impl 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}
2132impl ast::TypeBoundsOwner for WherePred {}
2133impl 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)]
2141pub struct WhereClause {
2142 pub(crate) syntax: SyntaxNode,
2143}
2144impl AstNode for WhereClause { 2597impl 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}
2155impl 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)]
2161pub struct Abi {
2162 pub(crate) syntax: SyntaxNode,
2163}
2164impl AstNode for Abi { 2608impl 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}
2175impl Abi {}
2176
2177#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2178pub struct ExprStmt {
2179 pub(crate) syntax: SyntaxNode,
2180}
2181impl AstNode for ExprStmt { 2619impl 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}
2192impl ast::AttrsOwner for ExprStmt {}
2193impl 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)]
2199pub struct LetStmt {
2200 pub(crate) syntax: SyntaxNode,
2201}
2202impl AstNode for LetStmt { 2630impl 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}
2213impl ast::AttrsOwner for LetStmt {}
2214impl ast::TypeAscriptionOwner for LetStmt {}
2215impl 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)]
2224pub struct Condition {
2225 pub(crate) syntax: SyntaxNode,
2226}
2227impl AstNode for Condition { 2641impl 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}
2238impl 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)]
2246pub struct Block {
2247 pub(crate) syntax: SyntaxNode,
2248}
2249impl AstNode for Block { 2652impl 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}
2260impl ast::AttrsOwner for Block {}
2261impl ast::ModuleItemOwner for Block {}
2262impl 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)]
2270pub struct ParamList {
2271 pub(crate) syntax: SyntaxNode,
2272}
2273impl AstNode for ParamList { 2663impl 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}
2284impl 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)]
2292pub struct SelfParam {
2293 pub(crate) syntax: SyntaxNode,
2294}
2295impl AstNode for SelfParam { 2674impl 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}
2306impl ast::TypeAscriptionOwner for SelfParam {}
2307impl ast::AttrsOwner for SelfParam {}
2308impl 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)]
2318pub struct Param {
2319 pub(crate) syntax: SyntaxNode,
2320}
2321impl AstNode for Param { 2685impl 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}
2332impl ast::TypeAscriptionOwner for Param {}
2333impl ast::AttrsOwner for Param {}
2334impl 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)]
2340pub struct UseItem {
2341 pub(crate) syntax: SyntaxNode,
2342}
2343impl AstNode for UseItem { 2696impl 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}
2354impl ast::AttrsOwner for UseItem {}
2355impl ast::VisibilityOwner for UseItem {}
2356impl 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)]
2362pub struct UseTree {
2363 pub(crate) syntax: SyntaxNode,
2364}
2365impl AstNode for UseTree { 2707impl 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}
2376impl 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)]
2384pub struct Alias {
2385 pub(crate) syntax: SyntaxNode,
2386}
2387impl AstNode for Alias { 2718impl 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}
2398impl ast::NameOwner for Alias {}
2399impl Alias {
2400 pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
2401}
2402
2403#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2404pub struct UseTreeList {
2405 pub(crate) syntax: SyntaxNode,
2406}
2407impl AstNode for UseTreeList { 2729impl 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}
2418impl 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)]
2425pub struct ExternCrateItem {
2426 pub(crate) syntax: SyntaxNode,
2427}
2428impl AstNode for ExternCrateItem { 2740impl 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}
2439impl ast::AttrsOwner for ExternCrateItem {}
2440impl ast::VisibilityOwner for ExternCrateItem {}
2441impl 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)]
2449pub struct ArgList {
2450 pub(crate) syntax: SyntaxNode,
2451}
2452impl AstNode for ArgList { 2751impl 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}
2463impl 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)]
2470pub struct Path {
2471 pub(crate) syntax: SyntaxNode,
2472}
2473impl AstNode for Path { 2762impl 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}
2484impl 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)]
2490pub struct PathSegment {
2491 pub(crate) syntax: SyntaxNode,
2492}
2493impl AstNode for PathSegment { 2773impl 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}
2504impl 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)]
2516pub struct TypeArgList {
2517 pub(crate) syntax: SyntaxNode,
2518}
2519impl AstNode for TypeArgList { 2784impl 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}
2530impl 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)]
2542pub struct TypeArg {
2543 pub(crate) syntax: SyntaxNode,
2544}
2545impl AstNode for TypeArg { 2795impl 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}
2556impl TypeArg {
2557 pub fn type_ref(&self) -> Option<TypeRef> { support::child(&self.syntax) }
2558}
2559
2560#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2561pub struct AssocTypeArg {
2562 pub(crate) syntax: SyntaxNode,
2563}
2564impl AstNode for AssocTypeArg { 2806impl 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}
2575impl ast::TypeBoundsOwner for AssocTypeArg {}
2576impl 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)]
2583pub struct LifetimeArg {
2584 pub(crate) syntax: SyntaxNode,
2585}
2586impl AstNode for LifetimeArg { 2817impl 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}
2597impl 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)]
2604pub struct ConstArg {
2605 pub(crate) syntax: SyntaxNode,
2606}
2607impl AstNode for ConstArg { 2828impl 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}
2618impl 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)]
2625pub struct MacroItems {
2626 pub(crate) syntax: SyntaxNode,
2627}
2628impl AstNode for MacroItems { 2839impl 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}
2639impl ast::ModuleItemOwner for MacroItems {}
2640impl MacroItems {}
2641
2642#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2643pub struct MacroStmts {
2644 pub(crate) syntax: SyntaxNode,
2645}
2646impl AstNode for MacroStmts { 2850impl 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}
2657impl 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)]
2663pub struct ExternItemList {
2664 pub(crate) syntax: SyntaxNode,
2665}
2666impl AstNode for ExternItemList { 2861impl 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}
2677impl ast::ModuleItemOwner for ExternItemList {}
2678impl 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)]
2685pub struct ExternBlock {
2686 pub(crate) syntax: SyntaxNode,
2687}
2688impl AstNode for ExternBlock { 2872impl 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}
2699impl 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)]
2705pub struct MetaItem {
2706 pub(crate) syntax: SyntaxNode,
2707}
2708impl AstNode for MetaItem { 2883impl 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}
2719impl 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)]
2727pub struct MacroDef {
2728 pub(crate) syntax: SyntaxNode,
2729}
2730impl AstNode for MacroDef { 2894impl 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}
2741impl 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)]
2747pub enum NominalDef {
2748 StructDef(StructDef),
2749 EnumDef(EnumDef),
2750 UnionDef(UnionDef),
2751}
2752impl From<StructDef> for NominalDef { 2905impl 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}
2785impl ast::NameOwner for NominalDef {}
2786impl ast::TypeParamsOwner for NominalDef {}
2787impl ast::AttrsOwner for NominalDef {}
2788
2789#[derive(Debug, Clone, PartialEq, Eq, Hash)]
2790pub enum GenericParam {
2791 LifetimeParam(LifetimeParam),
2792 TypeParam(TypeParam),
2793 ConstParam(ConstParam),
2794}
2795impl From<LifetimeParam> for GenericParam { 2938impl 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)]
2830pub enum GenericArg {
2831 LifetimeArg(LifetimeArg),
2832 TypeArg(TypeArg),
2833 ConstArg(ConstArg),
2834 AssocTypeArg(AssocTypeArg),
2835}
2836impl From<LifetimeArg> for GenericArg { 2971impl 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)]
2876pub 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}
2891impl From<ParenType> for TypeRef { 3009impl 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)]
2978pub 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}
2994impl From<StructDef> for ModuleItem { 3094impl 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}
3084impl ast::NameOwner for ModuleItem {}
3085impl ast::AttrsOwner for ModuleItem {}
3086impl ast::VisibilityOwner for ModuleItem {}
3087
3088#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3089pub enum ImplItem {
3090 FnDef(FnDef),
3091 TypeAliasDef(TypeAliasDef),
3092 ConstDef(ConstDef),
3093}
3094impl From<FnDef> for ImplItem { 3184impl 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}
3127impl ast::NameOwner for ImplItem {}
3128impl ast::AttrsOwner for ImplItem {}
3129
3130#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3131pub enum ExternItem {
3132 FnDef(FnDef),
3133 StaticDef(StaticDef),
3134}
3135impl From<FnDef> for ExternItem { 3217impl 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}
3163impl ast::NameOwner for ExternItem {}
3164impl ast::AttrsOwner for ExternItem {}
3165impl ast::VisibilityOwner for ExternItem {}
3166
3167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3168pub 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}
3201impl From<TupleExpr> for Expr { 3245impl 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}
3379impl ast::AttrsOwner for Expr {}
3380
3381#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3382pub 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}
3399impl From<OrPat> for Pat { 3423impl 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)]
3496pub enum RecordInnerPat {
3497 RecordFieldPat(RecordFieldPat),
3498 BindPat(BindPat),
3499}
3500impl From<RecordFieldPat> for RecordInnerPat { 3518impl 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)]
3530pub enum AttrInput {
3531 Literal(Literal),
3532 TokenTree(TokenTree),
3533}
3534impl From<Literal> for AttrInput { 3546impl 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)]
3564pub enum Stmt {
3565 LetStmt(LetStmt),
3566 ExprStmt(ExprStmt),
3567}
3568impl From<LetStmt> for Stmt { 3574impl 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)]
3598pub enum FieldDefList {
3599 RecordFieldDefList(RecordFieldDefList),
3600 TupleFieldDefList(TupleFieldDefList),
3601}
3602impl From<RecordFieldDefList> for FieldDefList { 3602impl 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
296pub fn add_newlines(amount_of_newlines: usize, t: impl AstNode) -> ast::SourceFile { 296pub 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
301pub 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
306pub fn add_pub_crate_modifier(fn_def: ast::FnDef) -> ast::FnDef {
307 ast_from_text(&format!("pub(crate) {}", fn_def))
308}
309
301fn ast_from_text<N: AstNode>(text: &str) -> N { 310fn 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 "\
87ra-cli-parse 91rust-analyzer parse
88 92
89USAGE: 93USAGE:
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 "\
107ra-cli-symbols 111rust-analyzer symbols
108 112
109USAGE: 113USAGE:
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 "\
126ra-cli-highlight 130rust-analyzer highlight
127 131
128USAGE: 132USAGE:
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 "\
146ra-cli-analysis-stats 150rust-analyzer analysis-stats
147 151
148USAGE: 152USAGE:
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 "\
196rust-analyzer-analysis-bench 200rust-analyzer analysis-bench
197 201
198USAGE: 202USAGE:
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 "\
239ra-cli-diagnostics 243rust-analyzer diagnostics
240 244
241USAGE: 245USAGE:
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));
272ra-cli 276 }
277 };
278 Ok(Ok(Args { verbosity, command }))
279 }
280}
281
282fn print_subcommands() {
283 eprintln!(
284 "\
285rust-analyzer
273 286
274USAGE: 287USAGE:
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
294pub(crate) struct HelpPrinted; 304pub(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
68fn run_proc_macro_sv() -> Result<()> { 68fn 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
10use std::{ffi::OsString, path::PathBuf};
11
10use lsp_types::TextDocumentClientCapabilities; 12use lsp_types::TextDocumentClientCapabilities;
11use ra_flycheck::FlycheckConfig; 13use ra_flycheck::FlycheckConfig;
12use ra_ide::{CompletionConfig, InlayHintsConfig}; 14use 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};
27use semantic_tokens::{ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION}; 27use semantic_tokens::{
28 ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION, UNRESOLVED_REFERENCE,
29};
28 30
29pub trait Conv { 31pub 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
10pub(crate) const LIFETIME: SemanticTokenType = SemanticTokenType::new("lifetime"); 10pub(crate) const LIFETIME: SemanticTokenType = SemanticTokenType::new("lifetime");
11pub(crate) const TYPE_ALIAS: SemanticTokenType = SemanticTokenType::new("typeAlias"); 11pub(crate) const TYPE_ALIAS: SemanticTokenType = SemanticTokenType::new("typeAlias");
12pub(crate) const UNION: SemanticTokenType = SemanticTokenType::new("union"); 12pub(crate) const UNION: SemanticTokenType = SemanticTokenType::new("union");
13pub(crate) const UNRESOLVED_REFERENCE: SemanticTokenType =
14 SemanticTokenType::new("unresolvedReference");
13 15
14pub(crate) const CONSTANT: SemanticTokenModifier = SemanticTokenModifier::new("constant"); 16pub(crate) const CONSTANT: SemanticTokenModifier = SemanticTokenModifier::new("constant");
15pub(crate) const CONTROL_FLOW: SemanticTokenModifier = SemanticTokenModifier::new("controlFlow"); 17pub(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
48pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[ 51pub(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 @@
1mod support; 1mod support;
2 2
3use std::{collections::HashMap, time::Instant}; 3use std::{collections::HashMap, path::PathBuf, time::Instant};
4 4
5use lsp_types::{ 5use 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")