diff options
36 files changed, 468 insertions, 245 deletions
diff --git a/crates/assists/src/handlers/fill_match_arms.rs b/crates/assists/src/handlers/fill_match_arms.rs index cb60a3128..f9a62b9fa 100644 --- a/crates/assists/src/handlers/fill_match_arms.rs +++ b/crates/assists/src/handlers/fill_match_arms.rs | |||
@@ -196,7 +196,7 @@ fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::Variant) -> Optio | |||
196 | let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?); | 196 | let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?); |
197 | 197 | ||
198 | // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though | 198 | // FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though |
199 | let pat: ast::Pat = match var.source(db).value.kind() { | 199 | let pat: ast::Pat = match var.source(db)?.value.kind() { |
200 | ast::StructKind::Tuple(field_list) => { | 200 | ast::StructKind::Tuple(field_list) => { |
201 | let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count()); | 201 | let pats = iter::repeat(make::wildcard_pat().into()).take(field_list.fields().count()); |
202 | make::tuple_struct_pat(path, pats).into() | 202 | make::tuple_struct_pat(path, pats).into() |
diff --git a/crates/assists/src/handlers/fix_visibility.rs b/crates/assists/src/handlers/fix_visibility.rs index 8558a8ff0..de1e8f0bf 100644 --- a/crates/assists/src/handlers/fix_visibility.rs +++ b/crates/assists/src/handlers/fix_visibility.rs | |||
@@ -97,7 +97,8 @@ fn add_vis_to_referenced_record_field(acc: &mut Assists, ctx: &AssistContext) -> | |||
97 | let parent_name = parent.name(ctx.db()); | 97 | let parent_name = parent.name(ctx.db()); |
98 | let target_module = parent.module(ctx.db()); | 98 | let target_module = parent.module(ctx.db()); |
99 | 99 | ||
100 | let in_file_source = record_field_def.source(ctx.db()); | 100 | #[allow(deprecated)] |
101 | let in_file_source = record_field_def.source(ctx.db())?; | ||
101 | let (offset, current_visibility, target) = match in_file_source.value { | 102 | let (offset, current_visibility, target) = match in_file_source.value { |
102 | hir::FieldSource::Named(it) => { | 103 | hir::FieldSource::Named(it) => { |
103 | let s = it.syntax(); | 104 | let s = it.syntax(); |
@@ -145,53 +146,53 @@ fn target_data_for_def( | |||
145 | fn offset_target_and_file_id<S, Ast>( | 146 | fn offset_target_and_file_id<S, Ast>( |
146 | db: &dyn HirDatabase, | 147 | db: &dyn HirDatabase, |
147 | x: S, | 148 | x: S, |
148 | ) -> (TextSize, Option<ast::Visibility>, TextRange, FileId) | 149 | ) -> Option<(TextSize, Option<ast::Visibility>, TextRange, FileId)> |
149 | where | 150 | where |
150 | S: HasSource<Ast = Ast>, | 151 | S: HasSource<Ast = Ast>, |
151 | Ast: AstNode + ast::VisibilityOwner, | 152 | Ast: AstNode + ast::VisibilityOwner, |
152 | { | 153 | { |
153 | let source = x.source(db); | 154 | let source = x.source(db)?; |
154 | let in_file_syntax = source.syntax(); | 155 | let in_file_syntax = source.syntax(); |
155 | let file_id = in_file_syntax.file_id; | 156 | let file_id = in_file_syntax.file_id; |
156 | let syntax = in_file_syntax.value; | 157 | let syntax = in_file_syntax.value; |
157 | let current_visibility = source.value.visibility(); | 158 | let current_visibility = source.value.visibility(); |
158 | ( | 159 | Some(( |
159 | vis_offset(syntax), | 160 | vis_offset(syntax), |
160 | current_visibility, | 161 | current_visibility, |
161 | syntax.text_range(), | 162 | syntax.text_range(), |
162 | file_id.original_file(db.upcast()), | 163 | file_id.original_file(db.upcast()), |
163 | ) | 164 | )) |
164 | } | 165 | } |
165 | 166 | ||
166 | let target_name; | 167 | let target_name; |
167 | let (offset, current_visibility, target, target_file) = match def { | 168 | let (offset, current_visibility, target, target_file) = match def { |
168 | hir::ModuleDef::Function(f) => { | 169 | hir::ModuleDef::Function(f) => { |
169 | target_name = Some(f.name(db)); | 170 | target_name = Some(f.name(db)); |
170 | offset_target_and_file_id(db, f) | 171 | offset_target_and_file_id(db, f)? |
171 | } | 172 | } |
172 | hir::ModuleDef::Adt(adt) => { | 173 | hir::ModuleDef::Adt(adt) => { |
173 | target_name = Some(adt.name(db)); | 174 | target_name = Some(adt.name(db)); |
174 | match adt { | 175 | match adt { |
175 | hir::Adt::Struct(s) => offset_target_and_file_id(db, s), | 176 | hir::Adt::Struct(s) => offset_target_and_file_id(db, s)?, |
176 | hir::Adt::Union(u) => offset_target_and_file_id(db, u), | 177 | hir::Adt::Union(u) => offset_target_and_file_id(db, u)?, |
177 | hir::Adt::Enum(e) => offset_target_and_file_id(db, e), | 178 | hir::Adt::Enum(e) => offset_target_and_file_id(db, e)?, |
178 | } | 179 | } |
179 | } | 180 | } |
180 | hir::ModuleDef::Const(c) => { | 181 | hir::ModuleDef::Const(c) => { |
181 | target_name = c.name(db); | 182 | target_name = c.name(db); |
182 | offset_target_and_file_id(db, c) | 183 | offset_target_and_file_id(db, c)? |
183 | } | 184 | } |
184 | hir::ModuleDef::Static(s) => { | 185 | hir::ModuleDef::Static(s) => { |
185 | target_name = s.name(db); | 186 | target_name = s.name(db); |
186 | offset_target_and_file_id(db, s) | 187 | offset_target_and_file_id(db, s)? |
187 | } | 188 | } |
188 | hir::ModuleDef::Trait(t) => { | 189 | hir::ModuleDef::Trait(t) => { |
189 | target_name = Some(t.name(db)); | 190 | target_name = Some(t.name(db)); |
190 | offset_target_and_file_id(db, t) | 191 | offset_target_and_file_id(db, t)? |
191 | } | 192 | } |
192 | hir::ModuleDef::TypeAlias(t) => { | 193 | hir::ModuleDef::TypeAlias(t) => { |
193 | target_name = Some(t.name(db)); | 194 | target_name = Some(t.name(db)); |
194 | offset_target_and_file_id(db, t) | 195 | offset_target_and_file_id(db, t)? |
195 | } | 196 | } |
196 | hir::ModuleDef::Module(m) => { | 197 | hir::ModuleDef::Module(m) => { |
197 | target_name = m.name(db); | 198 | target_name = m.name(db); |
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs index 5a6125534..b05596446 100644 --- a/crates/assists/src/utils.rs +++ b/crates/assists/src/utils.rs | |||
@@ -98,10 +98,14 @@ pub fn filter_assoc_items( | |||
98 | 98 | ||
99 | items | 99 | items |
100 | .iter() | 100 | .iter() |
101 | .map(|i| match i { | 101 | // Note: This throws away items with no source. |
102 | hir::AssocItem::Function(i) => ast::AssocItem::Fn(i.source(db).value), | 102 | .filter_map(|i| { |
103 | hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAlias(i.source(db).value), | 103 | let item = match i { |
104 | hir::AssocItem::Const(i) => ast::AssocItem::Const(i.source(db).value), | 104 | hir::AssocItem::Function(i) => ast::AssocItem::Fn(i.source(db)?.value), |
105 | hir::AssocItem::TypeAlias(i) => ast::AssocItem::TypeAlias(i.source(db)?.value), | ||
106 | hir::AssocItem::Const(i) => ast::AssocItem::Const(i.source(db)?.value), | ||
107 | }; | ||
108 | Some(item) | ||
105 | }) | 109 | }) |
106 | .filter(has_def_name) | 110 | .filter(has_def_name) |
107 | .filter(|it| match it { | 111 | .filter(|it| match it { |
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs index d9fe13485..00c9e76f0 100644 --- a/crates/completion/src/completions.rs +++ b/crates/completion/src/completions.rs | |||
@@ -106,8 +106,9 @@ impl Completions { | |||
106 | func: hir::Function, | 106 | func: hir::Function, |
107 | local_name: Option<String>, | 107 | local_name: Option<String>, |
108 | ) { | 108 | ) { |
109 | let item = render_fn(RenderContext::new(ctx), None, local_name, func); | 109 | if let Some(item) = render_fn(RenderContext::new(ctx), None, local_name, func) { |
110 | self.add(item) | 110 | self.add(item) |
111 | } | ||
111 | } | 112 | } |
112 | 113 | ||
113 | pub(crate) fn add_variant_pat( | 114 | pub(crate) fn add_variant_pat( |
diff --git a/crates/completion/src/completions/trait_impl.rs b/crates/completion/src/completions/trait_impl.rs index c4e0d0669..54bb897e9 100644 --- a/crates/completion/src/completions/trait_impl.rs +++ b/crates/completion/src/completions/trait_impl.rs | |||
@@ -156,19 +156,21 @@ fn add_function_impl( | |||
156 | }; | 156 | }; |
157 | let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end()); | 157 | let range = TextRange::new(fn_def_node.text_range().start(), ctx.source_range().end()); |
158 | 158 | ||
159 | let function_decl = function_declaration(&func.source(ctx.db).value); | 159 | if let Some(src) = func.source(ctx.db) { |
160 | match ctx.config.snippet_cap { | 160 | let function_decl = function_declaration(&src.value); |
161 | Some(cap) => { | 161 | match ctx.config.snippet_cap { |
162 | let snippet = format!("{} {{\n $0\n}}", function_decl); | 162 | Some(cap) => { |
163 | builder.snippet_edit(cap, TextEdit::replace(range, snippet)) | 163 | let snippet = format!("{} {{\n $0\n}}", function_decl); |
164 | } | 164 | builder.snippet_edit(cap, TextEdit::replace(range, snippet)) |
165 | None => { | 165 | } |
166 | let header = format!("{} {{", function_decl); | 166 | None => { |
167 | builder.text_edit(TextEdit::replace(range, header)) | 167 | let header = format!("{} {{", function_decl); |
168 | builder.text_edit(TextEdit::replace(range, header)) | ||
169 | } | ||
168 | } | 170 | } |
171 | .kind(completion_kind) | ||
172 | .add_to(acc); | ||
169 | } | 173 | } |
170 | .kind(completion_kind) | ||
171 | .add_to(acc); | ||
172 | } | 174 | } |
173 | 175 | ||
174 | fn add_type_alias_impl( | 176 | fn add_type_alias_impl( |
@@ -200,16 +202,19 @@ fn add_const_impl( | |||
200 | let const_name = const_.name(ctx.db).map(|n| n.to_string()); | 202 | let const_name = const_.name(ctx.db).map(|n| n.to_string()); |
201 | 203 | ||
202 | if let Some(const_name) = const_name { | 204 | if let Some(const_name) = const_name { |
203 | let snippet = make_const_compl_syntax(&const_.source(ctx.db).value); | 205 | if let Some(source) = const_.source(ctx.db) { |
204 | 206 | let snippet = make_const_compl_syntax(&source.value); | |
205 | let range = TextRange::new(const_def_node.text_range().start(), ctx.source_range().end()); | 207 | |
206 | 208 | let range = | |
207 | CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) | 209 | TextRange::new(const_def_node.text_range().start(), ctx.source_range().end()); |
208 | .text_edit(TextEdit::replace(range, snippet)) | 210 | |
209 | .lookup_by(const_name) | 211 | CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone()) |
210 | .kind(CompletionItemKind::Const) | 212 | .text_edit(TextEdit::replace(range, snippet)) |
211 | .set_documentation(const_.docs(ctx.db)) | 213 | .lookup_by(const_name) |
212 | .add_to(acc); | 214 | .kind(CompletionItemKind::Const) |
215 | .set_documentation(const_.docs(ctx.db)) | ||
216 | .add_to(acc); | ||
217 | } | ||
213 | } | 218 | } |
214 | } | 219 | } |
215 | 220 | ||
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index 1ba7201a1..ac0b2a513 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs | |||
@@ -157,8 +157,7 @@ impl<'a> Render<'a> { | |||
157 | 157 | ||
158 | let kind = match resolution { | 158 | let kind = match resolution { |
159 | ScopeDef::ModuleDef(Function(func)) => { | 159 | ScopeDef::ModuleDef(Function(func)) => { |
160 | let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); | 160 | return render_fn(self.ctx, import_to_add, Some(local_name), *func); |
161 | return Some(item); | ||
162 | } | 161 | } |
163 | ScopeDef::ModuleDef(Variant(_)) | 162 | ScopeDef::ModuleDef(Variant(_)) |
164 | if self.ctx.completion.is_pat_binding_or_const | 163 | if self.ctx.completion.is_pat_binding_or_const |
diff --git a/crates/completion/src/render/const_.rs b/crates/completion/src/render/const_.rs index 039bdabc0..ce924f309 100644 --- a/crates/completion/src/render/const_.rs +++ b/crates/completion/src/render/const_.rs | |||
@@ -15,7 +15,7 @@ pub(crate) fn render_const<'a>( | |||
15 | ctx: RenderContext<'a>, | 15 | ctx: RenderContext<'a>, |
16 | const_: hir::Const, | 16 | const_: hir::Const, |
17 | ) -> Option<CompletionItem> { | 17 | ) -> Option<CompletionItem> { |
18 | ConstRender::new(ctx, const_).render() | 18 | ConstRender::new(ctx, const_)?.render() |
19 | } | 19 | } |
20 | 20 | ||
21 | #[derive(Debug)] | 21 | #[derive(Debug)] |
@@ -26,9 +26,9 @@ struct ConstRender<'a> { | |||
26 | } | 26 | } |
27 | 27 | ||
28 | impl<'a> ConstRender<'a> { | 28 | impl<'a> ConstRender<'a> { |
29 | fn new(ctx: RenderContext<'a>, const_: hir::Const) -> ConstRender<'a> { | 29 | fn new(ctx: RenderContext<'a>, const_: hir::Const) -> Option<ConstRender<'a>> { |
30 | let ast_node = const_.source(ctx.db()).value; | 30 | let ast_node = const_.source(ctx.db())?.value; |
31 | ConstRender { ctx, const_, ast_node } | 31 | Some(ConstRender { ctx, const_, ast_node }) |
32 | } | 32 | } |
33 | 33 | ||
34 | fn render(self) -> Option<CompletionItem> { | 34 | fn render(self) -> Option<CompletionItem> { |
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs index 316e05b52..081be14f4 100644 --- a/crates/completion/src/render/function.rs +++ b/crates/completion/src/render/function.rs | |||
@@ -14,9 +14,9 @@ pub(crate) fn render_fn<'a>( | |||
14 | import_to_add: Option<ImportEdit>, | 14 | import_to_add: Option<ImportEdit>, |
15 | local_name: Option<String>, | 15 | local_name: Option<String>, |
16 | fn_: hir::Function, | 16 | fn_: hir::Function, |
17 | ) -> CompletionItem { | 17 | ) -> Option<CompletionItem> { |
18 | let _p = profile::span("render_fn"); | 18 | let _p = profile::span("render_fn"); |
19 | FunctionRender::new(ctx, local_name, fn_).render(import_to_add) | 19 | Some(FunctionRender::new(ctx, local_name, fn_)?.render(import_to_add)) |
20 | } | 20 | } |
21 | 21 | ||
22 | #[derive(Debug)] | 22 | #[derive(Debug)] |
@@ -32,11 +32,11 @@ impl<'a> FunctionRender<'a> { | |||
32 | ctx: RenderContext<'a>, | 32 | ctx: RenderContext<'a>, |
33 | local_name: Option<String>, | 33 | local_name: Option<String>, |
34 | fn_: hir::Function, | 34 | fn_: hir::Function, |
35 | ) -> FunctionRender<'a> { | 35 | ) -> Option<FunctionRender<'a>> { |
36 | let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string()); | 36 | let name = local_name.unwrap_or_else(|| fn_.name(ctx.db()).to_string()); |
37 | let ast_node = fn_.source(ctx.db()).value; | 37 | let ast_node = fn_.source(ctx.db())?.value; |
38 | 38 | ||
39 | FunctionRender { ctx, name, func: fn_, ast_node } | 39 | Some(FunctionRender { ctx, name, func: fn_, ast_node }) |
40 | } | 40 | } |
41 | 41 | ||
42 | fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { | 42 | fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem { |
diff --git a/crates/completion/src/render/macro_.rs b/crates/completion/src/render/macro_.rs index dac79592f..6f4f9945c 100644 --- a/crates/completion/src/render/macro_.rs +++ b/crates/completion/src/render/macro_.rs | |||
@@ -39,20 +39,13 @@ impl<'a> MacroRender<'a> { | |||
39 | } | 39 | } |
40 | 40 | ||
41 | fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> { | 41 | fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> { |
42 | // FIXME: Currently proc-macro do not have ast-node, | ||
43 | // such that it does not have source | ||
44 | // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913 | ||
45 | if self.macro_.is_proc_macro() { | ||
46 | return None; | ||
47 | } | ||
48 | |||
49 | let mut builder = | 42 | let mut builder = |
50 | CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()) | 43 | CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), &self.label()) |
51 | .kind(CompletionItemKind::Macro) | 44 | .kind(CompletionItemKind::Macro) |
52 | .set_documentation(self.docs.clone()) | 45 | .set_documentation(self.docs.clone()) |
53 | .set_deprecated(self.ctx.is_deprecated(self.macro_)) | 46 | .set_deprecated(self.ctx.is_deprecated(self.macro_)) |
54 | .add_import(import_to_add) | 47 | .add_import(import_to_add) |
55 | .detail(self.detail()); | 48 | .set_detail(self.detail()); |
56 | 49 | ||
57 | let needs_bang = self.needs_bang(); | 50 | let needs_bang = self.needs_bang(); |
58 | builder = match self.ctx.snippet_cap() { | 51 | builder = match self.ctx.snippet_cap() { |
@@ -95,9 +88,9 @@ impl<'a> MacroRender<'a> { | |||
95 | format!("{}!", self.name) | 88 | format!("{}!", self.name) |
96 | } | 89 | } |
97 | 90 | ||
98 | fn detail(&self) -> String { | 91 | fn detail(&self) -> Option<String> { |
99 | let ast_node = self.macro_.source(self.ctx.db()).value; | 92 | let ast_node = self.macro_.source(self.ctx.db())?.value; |
100 | macro_label(&ast_node) | 93 | Some(macro_label(&ast_node)) |
101 | } | 94 | } |
102 | } | 95 | } |
103 | 96 | ||
diff --git a/crates/completion/src/render/type_alias.rs b/crates/completion/src/render/type_alias.rs index 9605c7fa9..69b445b9c 100644 --- a/crates/completion/src/render/type_alias.rs +++ b/crates/completion/src/render/type_alias.rs | |||
@@ -15,7 +15,7 @@ pub(crate) fn render_type_alias<'a>( | |||
15 | ctx: RenderContext<'a>, | 15 | ctx: RenderContext<'a>, |
16 | type_alias: hir::TypeAlias, | 16 | type_alias: hir::TypeAlias, |
17 | ) -> Option<CompletionItem> { | 17 | ) -> Option<CompletionItem> { |
18 | TypeAliasRender::new(ctx, type_alias).render() | 18 | TypeAliasRender::new(ctx, type_alias)?.render() |
19 | } | 19 | } |
20 | 20 | ||
21 | #[derive(Debug)] | 21 | #[derive(Debug)] |
@@ -26,9 +26,9 @@ struct TypeAliasRender<'a> { | |||
26 | } | 26 | } |
27 | 27 | ||
28 | impl<'a> TypeAliasRender<'a> { | 28 | impl<'a> TypeAliasRender<'a> { |
29 | fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> TypeAliasRender<'a> { | 29 | fn new(ctx: RenderContext<'a>, type_alias: hir::TypeAlias) -> Option<TypeAliasRender<'a>> { |
30 | let ast_node = type_alias.source(ctx.db()).value; | 30 | let ast_node = type_alias.source(ctx.db())?.value; |
31 | TypeAliasRender { ctx, type_alias, ast_node } | 31 | Some(TypeAliasRender { ctx, type_alias, ast_node }) |
32 | } | 32 | } |
33 | 33 | ||
34 | fn render(self) -> Option<CompletionItem> { | 34 | fn render(self) -> Option<CompletionItem> { |
diff --git a/crates/hir/src/attrs.rs b/crates/hir/src/attrs.rs index d32ce37ed..99fb65bac 100644 --- a/crates/hir/src/attrs.rs +++ b/crates/hir/src/attrs.rs | |||
@@ -3,15 +3,15 @@ use hir_def::{ | |||
3 | attr::{Attrs, Documentation}, | 3 | attr::{Attrs, Documentation}, |
4 | path::ModPath, | 4 | path::ModPath, |
5 | resolver::HasResolver, | 5 | resolver::HasResolver, |
6 | AttrDefId, ModuleDefId, | 6 | AttrDefId, GenericParamId, ModuleDefId, |
7 | }; | 7 | }; |
8 | use hir_expand::hygiene::Hygiene; | 8 | use hir_expand::hygiene::Hygiene; |
9 | use hir_ty::db::HirDatabase; | 9 | use hir_ty::db::HirDatabase; |
10 | use syntax::ast; | 10 | use syntax::ast; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | Adt, Const, Enum, Field, Function, MacroDef, Module, ModuleDef, Static, Struct, Trait, | 13 | Adt, Const, ConstParam, Enum, Field, Function, GenericParam, LifetimeParam, MacroDef, Module, |
14 | TypeAlias, Union, Variant, | 14 | ModuleDef, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | pub trait HasAttrs { | 17 | pub trait HasAttrs { |
@@ -62,25 +62,27 @@ impl_has_attrs![ | |||
62 | (Function, FunctionId), | 62 | (Function, FunctionId), |
63 | (Adt, AdtId), | 63 | (Adt, AdtId), |
64 | (Module, ModuleId), | 64 | (Module, ModuleId), |
65 | (GenericParam, GenericParamId), | ||
65 | ]; | 66 | ]; |
66 | 67 | ||
67 | macro_rules! impl_has_attrs_adt { | 68 | macro_rules! impl_has_attrs_enum { |
68 | ($($adt:ident),*) => {$( | 69 | ($($variant:ident),* for $enum:ident) => {$( |
69 | impl HasAttrs for $adt { | 70 | impl HasAttrs for $variant { |
70 | fn attrs(self, db: &dyn HirDatabase) -> Attrs { | 71 | fn attrs(self, db: &dyn HirDatabase) -> Attrs { |
71 | Adt::$adt(self).attrs(db) | 72 | $enum::$variant(self).attrs(db) |
72 | } | 73 | } |
73 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> { | 74 | fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> { |
74 | Adt::$adt(self).docs(db) | 75 | $enum::$variant(self).docs(db) |
75 | } | 76 | } |
76 | fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<ModuleDef> { | 77 | fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<ModuleDef> { |
77 | Adt::$adt(self).resolve_doc_path(db, link, ns) | 78 | $enum::$variant(self).resolve_doc_path(db, link, ns) |
78 | } | 79 | } |
79 | } | 80 | } |
80 | )*}; | 81 | )*}; |
81 | } | 82 | } |
82 | 83 | ||
83 | impl_has_attrs_adt![Struct, Union, Enum]; | 84 | impl_has_attrs_enum![Struct, Union, Enum for Adt]; |
85 | impl_has_attrs_enum![TypeParam, ConstParam, LifetimeParam for GenericParam]; | ||
84 | 86 | ||
85 | fn resolve_doc_path( | 87 | fn resolve_doc_path( |
86 | db: &dyn HirDatabase, | 88 | db: &dyn HirDatabase, |
@@ -99,6 +101,12 @@ fn resolve_doc_path( | |||
99 | AttrDefId::TraitId(it) => it.resolver(db.upcast()), | 101 | AttrDefId::TraitId(it) => it.resolver(db.upcast()), |
100 | AttrDefId::TypeAliasId(it) => it.resolver(db.upcast()), | 102 | AttrDefId::TypeAliasId(it) => it.resolver(db.upcast()), |
101 | AttrDefId::ImplId(it) => it.resolver(db.upcast()), | 103 | AttrDefId::ImplId(it) => it.resolver(db.upcast()), |
104 | AttrDefId::GenericParamId(it) => match it { | ||
105 | GenericParamId::TypeParamId(it) => it.parent, | ||
106 | GenericParamId::LifetimeParamId(it) => it.parent, | ||
107 | GenericParamId::ConstParamId(it) => it.parent, | ||
108 | } | ||
109 | .resolver(db.upcast()), | ||
102 | AttrDefId::MacroDefId(_) => return None, | 110 | AttrDefId::MacroDefId(_) => return None, |
103 | }; | 111 | }; |
104 | let path = ast::Path::parse(link).ok()?; | 112 | let path = ast::Path::parse(link).ok()?; |
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 97b7a8b5f..62eccf475 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -39,7 +39,7 @@ use hir_ty::{ | |||
39 | TyDefId, TyKind, TypeCtor, | 39 | TyDefId, TyKind, TypeCtor, |
40 | }; | 40 | }; |
41 | use rustc_hash::FxHashSet; | 41 | use rustc_hash::FxHashSet; |
42 | use stdx::impl_from; | 42 | use stdx::{format_to, impl_from}; |
43 | use syntax::{ | 43 | use syntax::{ |
44 | ast::{self, AttrsOwner, NameOwner}, | 44 | ast::{self, AttrsOwner, NameOwner}, |
45 | AstNode, SmolStr, | 45 | AstNode, SmolStr, |
@@ -797,6 +797,19 @@ impl Function { | |||
797 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { | 797 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { |
798 | db.function_data(self.id).has_body | 798 | db.function_data(self.id).has_body |
799 | } | 799 | } |
800 | |||
801 | /// A textual representation of the HIR of this function for debugging purposes. | ||
802 | pub fn debug_hir(self, db: &dyn HirDatabase) -> String { | ||
803 | let body = db.body(self.id.into()); | ||
804 | |||
805 | let mut result = String::new(); | ||
806 | format_to!(result, "HIR expressions in the body of `{}`:\n", self.name(db)); | ||
807 | for (id, expr) in body.exprs.iter() { | ||
808 | format_to!(result, "{:?}: {:?}\n", id, expr); | ||
809 | } | ||
810 | |||
811 | result | ||
812 | } | ||
800 | } | 813 | } |
801 | 814 | ||
802 | // Note: logically, this belongs to `hir_ty`, but we are not using it there yet. | 815 | // Note: logically, this belongs to `hir_ty`, but we are not using it there yet. |
@@ -983,13 +996,7 @@ impl MacroDef { | |||
983 | 996 | ||
984 | /// XXX: this parses the file | 997 | /// XXX: this parses the file |
985 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { | 998 | pub fn name(self, db: &dyn HirDatabase) -> Option<Name> { |
986 | // FIXME: Currently proc-macro do not have ast-node, | 999 | self.source(db)?.value.name().map(|it| it.as_name()) |
987 | // such that it does not have source | ||
988 | // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913 | ||
989 | if self.is_proc_macro() { | ||
990 | return None; | ||
991 | } | ||
992 | self.source(db).value.name().map(|it| it.as_name()) | ||
993 | } | 1000 | } |
994 | 1001 | ||
995 | /// Indicate it is a proc-macro | 1002 | /// Indicate it is a proc-macro |
@@ -1378,7 +1385,7 @@ impl Impl { | |||
1378 | } | 1385 | } |
1379 | 1386 | ||
1380 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { | 1387 | pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> { |
1381 | let src = self.source(db); | 1388 | let src = self.source(db)?; |
1382 | let item = src.file_id.is_builtin_derive(db.upcast())?; | 1389 | let item = src.file_id.is_builtin_derive(db.upcast())?; |
1383 | let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); | 1390 | let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id); |
1384 | 1391 | ||
diff --git a/crates/hir/src/from_id.rs b/crates/hir/src/from_id.rs index 2422887e3..3e47a5e9d 100644 --- a/crates/hir/src/from_id.rs +++ b/crates/hir/src/from_id.rs | |||
@@ -6,13 +6,13 @@ | |||
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | expr::{LabelId, PatId}, | 7 | expr::{LabelId, PatId}, |
8 | item_scope::ItemInNs, | 8 | item_scope::ItemInNs, |
9 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, GenericDefId, ModuleDefId, | 9 | AdtId, AssocItemId, DefWithBodyId, EnumVariantId, FieldId, GenericDefId, GenericParamId, |
10 | VariantId, | 10 | ModuleDefId, VariantId, |
11 | }; | 11 | }; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | Adt, AssocItem, DefWithBody, Field, GenericDef, Label, Local, MacroDef, ModuleDef, Variant, | 14 | code_model::GenericParam, Adt, AssocItem, DefWithBody, Field, GenericDef, Label, Local, |
15 | VariantDef, | 15 | MacroDef, ModuleDef, Variant, VariantDef, |
16 | }; | 16 | }; |
17 | 17 | ||
18 | macro_rules! from_id { | 18 | macro_rules! from_id { |
@@ -68,6 +68,26 @@ impl From<Adt> for AdtId { | |||
68 | } | 68 | } |
69 | } | 69 | } |
70 | 70 | ||
71 | impl From<GenericParamId> for GenericParam { | ||
72 | fn from(id: GenericParamId) -> Self { | ||
73 | match id { | ||
74 | GenericParamId::TypeParamId(it) => GenericParam::TypeParam(it.into()), | ||
75 | GenericParamId::LifetimeParamId(it) => GenericParam::LifetimeParam(it.into()), | ||
76 | GenericParamId::ConstParamId(it) => GenericParam::ConstParam(it.into()), | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | impl From<GenericParam> for GenericParamId { | ||
82 | fn from(id: GenericParam) -> Self { | ||
83 | match id { | ||
84 | GenericParam::TypeParam(it) => GenericParamId::TypeParamId(it.id), | ||
85 | GenericParam::LifetimeParam(it) => GenericParamId::LifetimeParamId(it.id), | ||
86 | GenericParam::ConstParam(it) => GenericParamId::ConstParamId(it.id), | ||
87 | } | ||
88 | } | ||
89 | } | ||
90 | |||
71 | impl From<EnumVariantId> for Variant { | 91 | impl From<EnumVariantId> for Variant { |
72 | fn from(id: EnumVariantId) -> Self { | 92 | fn from(id: EnumVariantId) -> Self { |
73 | Variant { parent: id.parent.into(), id: id.local_id } | 93 | Variant { parent: id.parent.into(), id: id.local_id } |
diff --git a/crates/hir/src/has_source.rs b/crates/hir/src/has_source.rs index dd7c0c570..7c57d8378 100644 --- a/crates/hir/src/has_source.rs +++ b/crates/hir/src/has_source.rs | |||
@@ -16,7 +16,7 @@ use crate::{ | |||
16 | 16 | ||
17 | pub trait HasSource { | 17 | pub trait HasSource { |
18 | type Ast; | 18 | type Ast; |
19 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast>; | 19 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>>; |
20 | } | 20 | } |
21 | 21 | ||
22 | /// NB: Module is !HasSource, because it has two source nodes at the same time: | 22 | /// NB: Module is !HasSource, because it has two source nodes at the same time: |
@@ -46,105 +46,104 @@ impl Module { | |||
46 | 46 | ||
47 | impl HasSource for Field { | 47 | impl HasSource for Field { |
48 | type Ast = FieldSource; | 48 | type Ast = FieldSource; |
49 | fn source(self, db: &dyn HirDatabase) -> InFile<FieldSource> { | 49 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
50 | let var = VariantId::from(self.parent); | 50 | let var = VariantId::from(self.parent); |
51 | let src = var.child_source(db.upcast()); | 51 | let src = var.child_source(db.upcast()); |
52 | src.map(|it| match it[self.id].clone() { | 52 | let field_source = src.map(|it| match it[self.id].clone() { |
53 | Either::Left(it) => FieldSource::Pos(it), | 53 | Either::Left(it) => FieldSource::Pos(it), |
54 | Either::Right(it) => FieldSource::Named(it), | 54 | Either::Right(it) => FieldSource::Named(it), |
55 | }) | 55 | }); |
56 | Some(field_source) | ||
56 | } | 57 | } |
57 | } | 58 | } |
58 | impl HasSource for Struct { | 59 | impl HasSource for Struct { |
59 | type Ast = ast::Struct; | 60 | type Ast = ast::Struct; |
60 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Struct> { | 61 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
61 | self.id.lookup(db.upcast()).source(db.upcast()) | 62 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
62 | } | 63 | } |
63 | } | 64 | } |
64 | impl HasSource for Union { | 65 | impl HasSource for Union { |
65 | type Ast = ast::Union; | 66 | type Ast = ast::Union; |
66 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Union> { | 67 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
67 | self.id.lookup(db.upcast()).source(db.upcast()) | 68 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
68 | } | 69 | } |
69 | } | 70 | } |
70 | impl HasSource for Enum { | 71 | impl HasSource for Enum { |
71 | type Ast = ast::Enum; | 72 | type Ast = ast::Enum; |
72 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Enum> { | 73 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
73 | self.id.lookup(db.upcast()).source(db.upcast()) | 74 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
74 | } | 75 | } |
75 | } | 76 | } |
76 | impl HasSource for Variant { | 77 | impl HasSource for Variant { |
77 | type Ast = ast::Variant; | 78 | type Ast = ast::Variant; |
78 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Variant> { | 79 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<ast::Variant>> { |
79 | self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone()) | 80 | Some(self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone())) |
80 | } | 81 | } |
81 | } | 82 | } |
82 | impl HasSource for Function { | 83 | impl HasSource for Function { |
83 | type Ast = ast::Fn; | 84 | type Ast = ast::Fn; |
84 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Fn> { | 85 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
85 | self.id.lookup(db.upcast()).source(db.upcast()) | 86 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
86 | } | 87 | } |
87 | } | 88 | } |
88 | impl HasSource for Const { | 89 | impl HasSource for Const { |
89 | type Ast = ast::Const; | 90 | type Ast = ast::Const; |
90 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Const> { | 91 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
91 | self.id.lookup(db.upcast()).source(db.upcast()) | 92 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
92 | } | 93 | } |
93 | } | 94 | } |
94 | impl HasSource for Static { | 95 | impl HasSource for Static { |
95 | type Ast = ast::Static; | 96 | type Ast = ast::Static; |
96 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Static> { | 97 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
97 | self.id.lookup(db.upcast()).source(db.upcast()) | 98 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
98 | } | 99 | } |
99 | } | 100 | } |
100 | impl HasSource for Trait { | 101 | impl HasSource for Trait { |
101 | type Ast = ast::Trait; | 102 | type Ast = ast::Trait; |
102 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Trait> { | 103 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
103 | self.id.lookup(db.upcast()).source(db.upcast()) | 104 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
104 | } | 105 | } |
105 | } | 106 | } |
106 | impl HasSource for TypeAlias { | 107 | impl HasSource for TypeAlias { |
107 | type Ast = ast::TypeAlias; | 108 | type Ast = ast::TypeAlias; |
108 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::TypeAlias> { | 109 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
109 | self.id.lookup(db.upcast()).source(db.upcast()) | 110 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
110 | } | 111 | } |
111 | } | 112 | } |
112 | impl HasSource for MacroDef { | 113 | impl HasSource for MacroDef { |
113 | type Ast = ast::Macro; | 114 | type Ast = ast::Macro; |
114 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Macro> { | 115 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
115 | InFile { | 116 | let ast_id = self.id.ast_id?; |
116 | file_id: self.id.ast_id.expect("MacroDef without ast_id").file_id, | 117 | Some(InFile { file_id: ast_id.file_id, value: ast_id.to_node(db.upcast()) }) |
117 | value: self.id.ast_id.expect("MacroDef without ast_id").to_node(db.upcast()), | ||
118 | } | ||
119 | } | 118 | } |
120 | } | 119 | } |
121 | impl HasSource for Impl { | 120 | impl HasSource for Impl { |
122 | type Ast = ast::Impl; | 121 | type Ast = ast::Impl; |
123 | fn source(self, db: &dyn HirDatabase) -> InFile<ast::Impl> { | 122 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
124 | self.id.lookup(db.upcast()).source(db.upcast()) | 123 | Some(self.id.lookup(db.upcast()).source(db.upcast())) |
125 | } | 124 | } |
126 | } | 125 | } |
127 | 126 | ||
128 | impl HasSource for TypeParam { | 127 | impl HasSource for TypeParam { |
129 | type Ast = Either<ast::Trait, ast::TypeParam>; | 128 | type Ast = Either<ast::Trait, ast::TypeParam>; |
130 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { | 129 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
131 | let child_source = self.id.parent.child_source(db.upcast()); | 130 | let child_source = self.id.parent.child_source(db.upcast()); |
132 | child_source.map(|it| it[self.id.local_id].clone()) | 131 | Some(child_source.map(|it| it[self.id.local_id].clone())) |
133 | } | 132 | } |
134 | } | 133 | } |
135 | 134 | ||
136 | impl HasSource for LifetimeParam { | 135 | impl HasSource for LifetimeParam { |
137 | type Ast = ast::LifetimeParam; | 136 | type Ast = ast::LifetimeParam; |
138 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { | 137 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
139 | let child_source = self.id.parent.child_source(db.upcast()); | 138 | let child_source = self.id.parent.child_source(db.upcast()); |
140 | child_source.map(|it| it[self.id.local_id].clone()) | 139 | Some(child_source.map(|it| it[self.id.local_id].clone())) |
141 | } | 140 | } |
142 | } | 141 | } |
143 | 142 | ||
144 | impl HasSource for ConstParam { | 143 | impl HasSource for ConstParam { |
145 | type Ast = ast::ConstParam; | 144 | type Ast = ast::ConstParam; |
146 | fn source(self, db: &dyn HirDatabase) -> InFile<Self::Ast> { | 145 | fn source(self, db: &dyn HirDatabase) -> Option<InFile<Self::Ast>> { |
147 | let child_source = self.id.parent.child_source(db.upcast()); | 146 | let child_source = self.id.parent.child_source(db.upcast()); |
148 | child_source.map(|it| it[self.id.local_id].clone()) | 147 | Some(child_source.map(|it| it[self.id.local_id].clone())) |
149 | } | 148 | } |
150 | } | 149 | } |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 8ac27e2dd..769945c47 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -35,8 +35,9 @@ pub use crate::{ | |||
35 | code_model::{ | 35 | code_model::{ |
36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, | 36 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const, |
37 | ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, | 37 | ConstParam, Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, |
38 | GenericDef, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, Module, ModuleDef, | 38 | GenericDef, GenericParam, HasVisibility, Impl, Label, LifetimeParam, Local, MacroDef, |
39 | ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef, | 39 | Module, ModuleDef, ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, |
40 | Variant, VariantDef, | ||
40 | }, | 41 | }, |
41 | has_source::HasSource, | 42 | has_source::HasSource, |
42 | semantics::{PathResolution, Semantics, SemanticsScope}, | 43 | semantics::{PathResolution, Semantics, SemanticsScope}, |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index fcf638e0f..6b79e7bad 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -21,7 +21,7 @@ use crate::{ | |||
21 | nameres::ModuleSource, | 21 | nameres::ModuleSource, |
22 | path::{ModPath, PathKind}, | 22 | path::{ModPath, PathKind}, |
23 | src::HasChildSource, | 23 | src::HasChildSource, |
24 | AdtId, AttrDefId, Lookup, | 24 | AdtId, AttrDefId, GenericParamId, Lookup, |
25 | }; | 25 | }; |
26 | 26 | ||
27 | /// Holds documentation | 27 | /// Holds documentation |
@@ -235,6 +235,25 @@ impl Attrs { | |||
235 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 235 | AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
236 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 236 | AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
237 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), | 237 | AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), |
238 | AttrDefId::GenericParamId(it) => match it { | ||
239 | GenericParamId::TypeParamId(it) => { | ||
240 | let src = it.parent.child_source(db); | ||
241 | RawAttrs::from_attrs_owner( | ||
242 | db, | ||
243 | src.with_value( | ||
244 | src.value[it.local_id].as_ref().either(|it| it as _, |it| it as _), | ||
245 | ), | ||
246 | ) | ||
247 | } | ||
248 | GenericParamId::LifetimeParamId(it) => { | ||
249 | let src = it.parent.child_source(db); | ||
250 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
251 | } | ||
252 | GenericParamId::ConstParamId(it) => { | ||
253 | let src = it.parent.child_source(db); | ||
254 | RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id])) | ||
255 | } | ||
256 | }, | ||
238 | }; | 257 | }; |
239 | 258 | ||
240 | raw_attrs.filter(db, def.krate(db)) | 259 | raw_attrs.filter(db, def.krate(db)) |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index 25f460504..211cb2faf 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -261,6 +261,15 @@ pub enum AdtId { | |||
261 | } | 261 | } |
262 | impl_from!(StructId, UnionId, EnumId for AdtId); | 262 | impl_from!(StructId, UnionId, EnumId for AdtId); |
263 | 263 | ||
264 | /// A generic param | ||
265 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] | ||
266 | pub enum GenericParamId { | ||
267 | TypeParamId(TypeParamId), | ||
268 | LifetimeParamId(LifetimeParamId), | ||
269 | ConstParamId(ConstParamId), | ||
270 | } | ||
271 | impl_from!(TypeParamId, LifetimeParamId, ConstParamId for GenericParamId); | ||
272 | |||
264 | /// The defs which can be visible in the module. | 273 | /// The defs which can be visible in the module. |
265 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 274 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
266 | pub enum ModuleDefId { | 275 | pub enum ModuleDefId { |
@@ -357,6 +366,7 @@ pub enum AttrDefId { | |||
357 | TypeAliasId(TypeAliasId), | 366 | TypeAliasId(TypeAliasId), |
358 | MacroDefId(MacroDefId), | 367 | MacroDefId(MacroDefId), |
359 | ImplId(ImplId), | 368 | ImplId(ImplId), |
369 | GenericParamId(GenericParamId), | ||
360 | } | 370 | } |
361 | 371 | ||
362 | impl_from!( | 372 | impl_from!( |
@@ -370,7 +380,8 @@ impl_from!( | |||
370 | TraitId, | 380 | TraitId, |
371 | TypeAliasId, | 381 | TypeAliasId, |
372 | MacroDefId, | 382 | MacroDefId, |
373 | ImplId | 383 | ImplId, |
384 | GenericParamId | ||
374 | for AttrDefId | 385 | for AttrDefId |
375 | ); | 386 | ); |
376 | 387 | ||
@@ -495,6 +506,15 @@ impl AttrDefId { | |||
495 | AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate, | 506 | AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate, |
496 | AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, | 507 | AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate, |
497 | AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate, | 508 | AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate, |
509 | AttrDefId::GenericParamId(it) => { | ||
510 | match it { | ||
511 | GenericParamId::TypeParamId(it) => it.parent, | ||
512 | GenericParamId::LifetimeParamId(it) => it.parent, | ||
513 | GenericParamId::ConstParamId(it) => it.parent, | ||
514 | } | ||
515 | .module(db) | ||
516 | .krate | ||
517 | } | ||
498 | // FIXME: `MacroDefId` should store the defining module, then this can implement | 518 | // FIXME: `MacroDefId` should store the defining module, then this can implement |
499 | // `HasModule` | 519 | // `HasModule` |
500 | AttrDefId::MacroDefId(it) => it.krate, | 520 | AttrDefId::MacroDefId(it) => it.krate, |
diff --git a/crates/ide/src/call_hierarchy.rs b/crates/ide/src/call_hierarchy.rs index 60e0cd4ad..3c2d39f5d 100644 --- a/crates/ide/src/call_hierarchy.rs +++ b/crates/ide/src/call_hierarchy.rs | |||
@@ -8,7 +8,7 @@ use ide_db::RootDatabase; | |||
8 | use syntax::{ast, match_ast, AstNode, TextRange}; | 8 | use syntax::{ast, match_ast, AstNode, TextRange}; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | display::ToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, | 11 | display::TryToNav, goto_definition, references, FilePosition, NavigationTarget, RangeInfo, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | #[derive(Debug, Clone)] | 14 | #[derive(Debug, Clone)] |
@@ -61,7 +61,7 @@ pub(crate) fn incoming_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
61 | match node { | 61 | match node { |
62 | ast::Fn(it) => { | 62 | ast::Fn(it) => { |
63 | let def = sema.to_def(&it)?; | 63 | let def = sema.to_def(&it)?; |
64 | Some(def.to_nav(sema.db)) | 64 | def.try_to_nav(sema.db) |
65 | }, | 65 | }, |
66 | _ => None, | 66 | _ => None, |
67 | } | 67 | } |
@@ -99,7 +99,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
99 | match callable.kind() { | 99 | match callable.kind() { |
100 | hir::CallableKind::Function(it) => { | 100 | hir::CallableKind::Function(it) => { |
101 | let fn_def: hir::Function = it.into(); | 101 | let fn_def: hir::Function = it.into(); |
102 | let nav = fn_def.to_nav(db); | 102 | let nav = fn_def.try_to_nav(db)?; |
103 | Some(nav) | 103 | Some(nav) |
104 | } | 104 | } |
105 | _ => None, | 105 | _ => None, |
@@ -107,7 +107,7 @@ pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Optio | |||
107 | } | 107 | } |
108 | FnCallNode::MethodCallExpr(expr) => { | 108 | FnCallNode::MethodCallExpr(expr) => { |
109 | let function = sema.resolve_method_call(&expr)?; | 109 | let function = sema.resolve_method_call(&expr)?; |
110 | Some(function.to_nav(db)) | 110 | function.try_to_nav(db) |
111 | } | 111 | } |
112 | } { | 112 | } { |
113 | Some((func_target, name_ref.syntax().text_range())) | 113 | Some((func_target, name_ref.syntax().text_range())) |
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs index d79f5c170..ec0f840e9 100644 --- a/crates/ide/src/diagnostics/fixes.rs +++ b/crates/ide/src/diagnostics/fixes.rs | |||
@@ -156,20 +156,23 @@ fn missing_record_expr_field_fix( | |||
156 | let record_fields = match VariantDef::from(def_id) { | 156 | let record_fields = match VariantDef::from(def_id) { |
157 | VariantDef::Struct(s) => { | 157 | VariantDef::Struct(s) => { |
158 | module = s.module(sema.db); | 158 | module = s.module(sema.db); |
159 | let source = s.source(sema.db); | 159 | #[allow(deprecated)] |
160 | let source = s.source(sema.db)?; | ||
160 | def_file_id = source.file_id; | 161 | def_file_id = source.file_id; |
161 | let fields = source.value.field_list()?; | 162 | let fields = source.value.field_list()?; |
162 | record_field_list(fields)? | 163 | record_field_list(fields)? |
163 | } | 164 | } |
164 | VariantDef::Union(u) => { | 165 | VariantDef::Union(u) => { |
165 | module = u.module(sema.db); | 166 | module = u.module(sema.db); |
166 | let source = u.source(sema.db); | 167 | #[allow(deprecated)] |
168 | let source = u.source(sema.db)?; | ||
167 | def_file_id = source.file_id; | 169 | def_file_id = source.file_id; |
168 | source.value.record_field_list()? | 170 | source.value.record_field_list()? |
169 | } | 171 | } |
170 | VariantDef::Variant(e) => { | 172 | VariantDef::Variant(e) => { |
171 | module = e.module(sema.db); | 173 | module = e.module(sema.db); |
172 | let source = e.source(sema.db); | 174 | #[allow(deprecated)] |
175 | let source = e.source(sema.db)?; | ||
173 | def_file_id = source.file_id; | 176 | def_file_id = source.file_id; |
174 | let fields = source.value.field_list()?; | 177 | let fields = source.value.field_list()?; |
175 | record_field_list(fields)? | 178 | record_field_list(fields)? |
diff --git a/crates/ide/src/display/navigation_target.rs b/crates/ide/src/display/navigation_target.rs index bcde2b6f1..e24c78301 100644 --- a/crates/ide/src/display/navigation_target.rs +++ b/crates/ide/src/display/navigation_target.rs | |||
@@ -210,41 +210,32 @@ impl ToNav for FileSymbol { | |||
210 | impl TryToNav for Definition { | 210 | impl TryToNav for Definition { |
211 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { | 211 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
212 | match self { | 212 | match self { |
213 | Definition::Macro(it) => { | 213 | Definition::Macro(it) => it.try_to_nav(db), |
214 | // FIXME: Currently proc-macro do not have ast-node, | 214 | Definition::Field(it) => it.try_to_nav(db), |
215 | // such that it does not have source | ||
216 | // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913 | ||
217 | if it.is_proc_macro() { | ||
218 | return None; | ||
219 | } | ||
220 | Some(it.to_nav(db)) | ||
221 | } | ||
222 | Definition::Field(it) => Some(it.to_nav(db)), | ||
223 | Definition::ModuleDef(it) => it.try_to_nav(db), | 215 | Definition::ModuleDef(it) => it.try_to_nav(db), |
224 | Definition::SelfType(it) => Some(it.to_nav(db)), | 216 | Definition::SelfType(it) => it.try_to_nav(db), |
225 | Definition::Local(it) => Some(it.to_nav(db)), | 217 | Definition::Local(it) => Some(it.to_nav(db)), |
226 | Definition::TypeParam(it) => Some(it.to_nav(db)), | 218 | Definition::TypeParam(it) => it.try_to_nav(db), |
227 | Definition::LifetimeParam(it) => Some(it.to_nav(db)), | 219 | Definition::LifetimeParam(it) => it.try_to_nav(db), |
228 | Definition::Label(it) => Some(it.to_nav(db)), | 220 | Definition::Label(it) => Some(it.to_nav(db)), |
229 | Definition::ConstParam(it) => Some(it.to_nav(db)), | 221 | Definition::ConstParam(it) => it.try_to_nav(db), |
230 | } | 222 | } |
231 | } | 223 | } |
232 | } | 224 | } |
233 | 225 | ||
234 | impl TryToNav for hir::ModuleDef { | 226 | impl TryToNav for hir::ModuleDef { |
235 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { | 227 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
236 | let res = match self { | 228 | match self { |
237 | hir::ModuleDef::Module(it) => it.to_nav(db), | 229 | hir::ModuleDef::Module(it) => Some(it.to_nav(db)), |
238 | hir::ModuleDef::Function(it) => it.to_nav(db), | 230 | hir::ModuleDef::Function(it) => it.try_to_nav(db), |
239 | hir::ModuleDef::Adt(it) => it.to_nav(db), | 231 | hir::ModuleDef::Adt(it) => it.try_to_nav(db), |
240 | hir::ModuleDef::Variant(it) => it.to_nav(db), | 232 | hir::ModuleDef::Variant(it) => it.try_to_nav(db), |
241 | hir::ModuleDef::Const(it) => it.to_nav(db), | 233 | hir::ModuleDef::Const(it) => it.try_to_nav(db), |
242 | hir::ModuleDef::Static(it) => it.to_nav(db), | 234 | hir::ModuleDef::Static(it) => it.try_to_nav(db), |
243 | hir::ModuleDef::Trait(it) => it.to_nav(db), | 235 | hir::ModuleDef::Trait(it) => it.try_to_nav(db), |
244 | hir::ModuleDef::TypeAlias(it) => it.to_nav(db), | 236 | hir::ModuleDef::TypeAlias(it) => it.try_to_nav(db), |
245 | hir::ModuleDef::BuiltinType(_) => return None, | 237 | hir::ModuleDef::BuiltinType(_) => None, |
246 | }; | 238 | } |
247 | Some(res) | ||
248 | } | 239 | } |
249 | } | 240 | } |
250 | 241 | ||
@@ -279,13 +270,13 @@ impl ToNavFromAst for hir::Trait { | |||
279 | const KIND: SymbolKind = SymbolKind::Trait; | 270 | const KIND: SymbolKind = SymbolKind::Trait; |
280 | } | 271 | } |
281 | 272 | ||
282 | impl<D> ToNav for D | 273 | impl<D> TryToNav for D |
283 | where | 274 | where |
284 | D: HasSource + ToNavFromAst + Copy + HasAttrs, | 275 | D: HasSource + ToNavFromAst + Copy + HasAttrs, |
285 | D::Ast: ast::NameOwner + ShortLabel, | 276 | D::Ast: ast::NameOwner + ShortLabel, |
286 | { | 277 | { |
287 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 278 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
288 | let src = self.source(db); | 279 | let src = self.source(db)?; |
289 | let mut res = NavigationTarget::from_named( | 280 | let mut res = NavigationTarget::from_named( |
290 | db, | 281 | db, |
291 | src.as_ref().map(|it| it as &dyn ast::NameOwner), | 282 | src.as_ref().map(|it| it as &dyn ast::NameOwner), |
@@ -293,7 +284,7 @@ where | |||
293 | ); | 284 | ); |
294 | res.docs = self.docs(db); | 285 | res.docs = self.docs(db); |
295 | res.description = src.value.short_label(); | 286 | res.description = src.value.short_label(); |
296 | res | 287 | Some(res) |
297 | } | 288 | } |
298 | } | 289 | } |
299 | 290 | ||
@@ -312,9 +303,9 @@ impl ToNav for hir::Module { | |||
312 | } | 303 | } |
313 | } | 304 | } |
314 | 305 | ||
315 | impl ToNav for hir::Impl { | 306 | impl TryToNav for hir::Impl { |
316 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 307 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
317 | let src = self.source(db); | 308 | let src = self.source(db)?; |
318 | let derive_attr = self.is_builtin_derive(db); | 309 | let derive_attr = self.is_builtin_derive(db); |
319 | let frange = if let Some(item) = &derive_attr { | 310 | let frange = if let Some(item) = &derive_attr { |
320 | item.syntax().original_file_range(db) | 311 | item.syntax().original_file_range(db) |
@@ -327,21 +318,21 @@ impl ToNav for hir::Impl { | |||
327 | src.value.self_ty().map(|ty| src.with_value(ty.syntax()).original_file_range(db).range) | 318 | src.value.self_ty().map(|ty| src.with_value(ty.syntax()).original_file_range(db).range) |
328 | }; | 319 | }; |
329 | 320 | ||
330 | NavigationTarget::from_syntax( | 321 | Some(NavigationTarget::from_syntax( |
331 | frange.file_id, | 322 | frange.file_id, |
332 | "impl".into(), | 323 | "impl".into(), |
333 | focus_range, | 324 | focus_range, |
334 | frange.range, | 325 | frange.range, |
335 | SymbolKind::Impl, | 326 | SymbolKind::Impl, |
336 | ) | 327 | )) |
337 | } | 328 | } |
338 | } | 329 | } |
339 | 330 | ||
340 | impl ToNav for hir::Field { | 331 | impl TryToNav for hir::Field { |
341 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 332 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
342 | let src = self.source(db); | 333 | let src = self.source(db)?; |
343 | 334 | ||
344 | match &src.value { | 335 | let field_source = match &src.value { |
345 | FieldSource::Named(it) => { | 336 | FieldSource::Named(it) => { |
346 | let mut res = | 337 | let mut res = |
347 | NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); | 338 | NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field); |
@@ -359,13 +350,14 @@ impl ToNav for hir::Field { | |||
359 | SymbolKind::Field, | 350 | SymbolKind::Field, |
360 | ) | 351 | ) |
361 | } | 352 | } |
362 | } | 353 | }; |
354 | Some(field_source) | ||
363 | } | 355 | } |
364 | } | 356 | } |
365 | 357 | ||
366 | impl ToNav for hir::MacroDef { | 358 | impl TryToNav for hir::MacroDef { |
367 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 359 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
368 | let src = self.source(db); | 360 | let src = self.source(db)?; |
369 | log::debug!("nav target {:#?}", src.value.syntax()); | 361 | log::debug!("nav target {:#?}", src.value.syntax()); |
370 | let mut res = NavigationTarget::from_named( | 362 | let mut res = NavigationTarget::from_named( |
371 | db, | 363 | db, |
@@ -373,26 +365,26 @@ impl ToNav for hir::MacroDef { | |||
373 | SymbolKind::Macro, | 365 | SymbolKind::Macro, |
374 | ); | 366 | ); |
375 | res.docs = self.docs(db); | 367 | res.docs = self.docs(db); |
376 | res | 368 | Some(res) |
377 | } | 369 | } |
378 | } | 370 | } |
379 | 371 | ||
380 | impl ToNav for hir::Adt { | 372 | impl TryToNav for hir::Adt { |
381 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 373 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
382 | match self { | 374 | match self { |
383 | hir::Adt::Struct(it) => it.to_nav(db), | 375 | hir::Adt::Struct(it) => it.try_to_nav(db), |
384 | hir::Adt::Union(it) => it.to_nav(db), | 376 | hir::Adt::Union(it) => it.try_to_nav(db), |
385 | hir::Adt::Enum(it) => it.to_nav(db), | 377 | hir::Adt::Enum(it) => it.try_to_nav(db), |
386 | } | 378 | } |
387 | } | 379 | } |
388 | } | 380 | } |
389 | 381 | ||
390 | impl ToNav for hir::AssocItem { | 382 | impl TryToNav for hir::AssocItem { |
391 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 383 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
392 | match self { | 384 | match self { |
393 | AssocItem::Function(it) => it.to_nav(db), | 385 | AssocItem::Function(it) => it.try_to_nav(db), |
394 | AssocItem::Const(it) => it.to_nav(db), | 386 | AssocItem::Const(it) => it.try_to_nav(db), |
395 | AssocItem::TypeAlias(it) => it.to_nav(db), | 387 | AssocItem::TypeAlias(it) => it.try_to_nav(db), |
396 | } | 388 | } |
397 | } | 389 | } |
398 | } | 390 | } |
@@ -446,9 +438,9 @@ impl ToNav for hir::Label { | |||
446 | } | 438 | } |
447 | } | 439 | } |
448 | 440 | ||
449 | impl ToNav for hir::TypeParam { | 441 | impl TryToNav for hir::TypeParam { |
450 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 442 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
451 | let src = self.source(db); | 443 | let src = self.source(db)?; |
452 | let full_range = match &src.value { | 444 | let full_range = match &src.value { |
453 | Either::Left(it) => it.syntax().text_range(), | 445 | Either::Left(it) => it.syntax().text_range(), |
454 | Either::Right(it) => it.syntax().text_range(), | 446 | Either::Right(it) => it.syntax().text_range(), |
@@ -457,7 +449,7 @@ impl ToNav for hir::TypeParam { | |||
457 | Either::Left(_) => None, | 449 | Either::Left(_) => None, |
458 | Either::Right(it) => it.name().map(|it| it.syntax().text_range()), | 450 | Either::Right(it) => it.name().map(|it| it.syntax().text_range()), |
459 | }; | 451 | }; |
460 | NavigationTarget { | 452 | Some(NavigationTarget { |
461 | file_id: src.file_id.original_file(db), | 453 | file_id: src.file_id.original_file(db), |
462 | name: self.name(db).to_string().into(), | 454 | name: self.name(db).to_string().into(), |
463 | kind: Some(SymbolKind::TypeParam), | 455 | kind: Some(SymbolKind::TypeParam), |
@@ -466,15 +458,15 @@ impl ToNav for hir::TypeParam { | |||
466 | container_name: None, | 458 | container_name: None, |
467 | description: None, | 459 | description: None, |
468 | docs: None, | 460 | docs: None, |
469 | } | 461 | }) |
470 | } | 462 | } |
471 | } | 463 | } |
472 | 464 | ||
473 | impl ToNav for hir::LifetimeParam { | 465 | impl TryToNav for hir::LifetimeParam { |
474 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 466 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
475 | let src = self.source(db); | 467 | let src = self.source(db)?; |
476 | let full_range = src.value.syntax().text_range(); | 468 | let full_range = src.value.syntax().text_range(); |
477 | NavigationTarget { | 469 | Some(NavigationTarget { |
478 | file_id: src.file_id.original_file(db), | 470 | file_id: src.file_id.original_file(db), |
479 | name: self.name(db).to_string().into(), | 471 | name: self.name(db).to_string().into(), |
480 | kind: Some(SymbolKind::LifetimeParam), | 472 | kind: Some(SymbolKind::LifetimeParam), |
@@ -483,15 +475,15 @@ impl ToNav for hir::LifetimeParam { | |||
483 | container_name: None, | 475 | container_name: None, |
484 | description: None, | 476 | description: None, |
485 | docs: None, | 477 | docs: None, |
486 | } | 478 | }) |
487 | } | 479 | } |
488 | } | 480 | } |
489 | 481 | ||
490 | impl ToNav for hir::ConstParam { | 482 | impl TryToNav for hir::ConstParam { |
491 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | 483 | fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> { |
492 | let src = self.source(db); | 484 | let src = self.source(db)?; |
493 | let full_range = src.value.syntax().text_range(); | 485 | let full_range = src.value.syntax().text_range(); |
494 | NavigationTarget { | 486 | Some(NavigationTarget { |
495 | file_id: src.file_id.original_file(db), | 487 | file_id: src.file_id.original_file(db), |
496 | name: self.name(db).to_string().into(), | 488 | name: self.name(db).to_string().into(), |
497 | kind: Some(SymbolKind::ConstParam), | 489 | kind: Some(SymbolKind::ConstParam), |
@@ -500,7 +492,7 @@ impl ToNav for hir::ConstParam { | |||
500 | container_name: None, | 492 | container_name: None, |
501 | description: None, | 493 | description: None, |
502 | docs: None, | 494 | docs: None, |
503 | } | 495 | }) |
504 | } | 496 | } |
505 | } | 497 | } |
506 | 498 | ||
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs index 6eac39639..da9378a97 100644 --- a/crates/ide/src/goto_implementation.rs +++ b/crates/ide/src/goto_implementation.rs | |||
@@ -2,7 +2,7 @@ use hir::{Crate, Impl, Semantics}; | |||
2 | use ide_db::RootDatabase; | 2 | use ide_db::RootDatabase; |
3 | use syntax::{algo::find_node_at_offset, ast, AstNode}; | 3 | use syntax::{algo::find_node_at_offset, ast, AstNode}; |
4 | 4 | ||
5 | use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; | 5 | use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo}; |
6 | 6 | ||
7 | // Feature: Go to Implementation | 7 | // Feature: Go to Implementation |
8 | // | 8 | // |
@@ -55,7 +55,7 @@ fn impls_for_def( | |||
55 | impls | 55 | impls |
56 | .into_iter() | 56 | .into_iter() |
57 | .filter(|impl_def| ty.is_equal_for_find_impls(&impl_def.target_ty(sema.db))) | 57 | .filter(|impl_def| ty.is_equal_for_find_impls(&impl_def.target_ty(sema.db))) |
58 | .map(|imp| imp.to_nav(sema.db)) | 58 | .filter_map(|imp| imp.try_to_nav(sema.db)) |
59 | .collect(), | 59 | .collect(), |
60 | ) | 60 | ) |
61 | } | 61 | } |
@@ -69,7 +69,7 @@ fn impls_for_trait( | |||
69 | 69 | ||
70 | let impls = Impl::for_trait(sema.db, krate, tr); | 70 | let impls = Impl::for_trait(sema.db, krate, tr); |
71 | 71 | ||
72 | Some(impls.into_iter().map(|imp| imp.to_nav(sema.db)).collect()) | 72 | Some(impls.into_iter().filter_map(|imp| imp.try_to_nav(sema.db)).collect()) |
73 | } | 73 | } |
74 | 74 | ||
75 | #[cfg(test)] | 75 | #[cfg(test)] |
diff --git a/crates/ide/src/goto_type_definition.rs b/crates/ide/src/goto_type_definition.rs index aba6bf5dc..7e84e06be 100644 --- a/crates/ide/src/goto_type_definition.rs +++ b/crates/ide/src/goto_type_definition.rs | |||
@@ -1,7 +1,7 @@ | |||
1 | use ide_db::RootDatabase; | 1 | use ide_db::RootDatabase; |
2 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; | 2 | use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, T}; |
3 | 3 | ||
4 | use crate::{display::ToNav, FilePosition, NavigationTarget, RangeInfo}; | 4 | use crate::{display::TryToNav, FilePosition, NavigationTarget, RangeInfo}; |
5 | 5 | ||
6 | // Feature: Go to Type Definition | 6 | // Feature: Go to Type Definition |
7 | // | 7 | // |
@@ -37,7 +37,7 @@ pub(crate) fn goto_type_definition( | |||
37 | 37 | ||
38 | let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; | 38 | let adt_def = ty.autoderef(db).filter_map(|ty| ty.as_adt()).last()?; |
39 | 39 | ||
40 | let nav = adt_def.to_nav(db); | 40 | let nav = adt_def.try_to_nav(db)?; |
41 | Some(RangeInfo::new(node.text_range(), vec![nav])) | 41 | Some(RangeInfo::new(node.text_range(), vec![nav])) |
42 | } | 42 | } |
43 | 43 | ||
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 98c7bfbe5..2737c900f 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -13,7 +13,7 @@ use syntax::{ast, match_ast, AstNode, SyntaxKind::*, SyntaxToken, TokenAtOffset, | |||
13 | use test_utils::mark; | 13 | use test_utils::mark; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | display::{macro_label, ShortLabel, ToNav, TryToNav}, | 16 | display::{macro_label, ShortLabel, TryToNav}, |
17 | doc_links::{remove_links, rewrite_links}, | 17 | doc_links::{remove_links, rewrite_links}, |
18 | markdown_remove::remove_markdown, | 18 | markdown_remove::remove_markdown, |
19 | markup::Markup, | 19 | markup::Markup, |
@@ -183,10 +183,10 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov | |||
183 | 183 | ||
184 | match def { | 184 | match def { |
185 | Definition::ModuleDef(it) => match it { | 185 | Definition::ModuleDef(it) => match it { |
186 | ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.to_nav(db))), | 186 | ModuleDef::Adt(Adt::Struct(it)) => Some(to_action(it.try_to_nav(db)?)), |
187 | ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.to_nav(db))), | 187 | ModuleDef::Adt(Adt::Union(it)) => Some(to_action(it.try_to_nav(db)?)), |
188 | ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.to_nav(db))), | 188 | ModuleDef::Adt(Adt::Enum(it)) => Some(to_action(it.try_to_nav(db)?)), |
189 | ModuleDef::Trait(it) => Some(to_action(it.to_nav(db))), | 189 | ModuleDef::Trait(it) => Some(to_action(it.try_to_nav(db)?)), |
190 | _ => None, | 190 | _ => None, |
191 | }, | 191 | }, |
192 | _ => None, | 192 | _ => None, |
@@ -206,7 +206,8 @@ fn runnable_action( | |||
206 | _ => None, | 206 | _ => None, |
207 | }, | 207 | }, |
208 | ModuleDef::Function(it) => { | 208 | ModuleDef::Function(it) => { |
209 | let src = it.source(sema.db); | 209 | #[allow(deprecated)] |
210 | let src = it.source(sema.db)?; | ||
210 | if src.file_id != file_id.into() { | 211 | if src.file_id != file_id.into() { |
211 | mark::hit!(hover_macro_generated_struct_fn_doc_comment); | 212 | mark::hit!(hover_macro_generated_struct_fn_doc_comment); |
212 | mark::hit!(hover_macro_generated_struct_fn_doc_attr); | 213 | mark::hit!(hover_macro_generated_struct_fn_doc_attr); |
@@ -326,17 +327,12 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
326 | let mod_path = definition_mod_path(db, &def); | 327 | let mod_path = definition_mod_path(db, &def); |
327 | return match def { | 328 | return match def { |
328 | Definition::Macro(it) => { | 329 | Definition::Macro(it) => { |
329 | // FIXME: Currently proc-macro do not have ast-node, | 330 | let label = macro_label(&it.source(db)?.value); |
330 | // such that it does not have source | ||
331 | // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913 | ||
332 | if it.is_proc_macro() { | ||
333 | return None; | ||
334 | } | ||
335 | let label = macro_label(&it.source(db).value); | ||
336 | from_def_source_labeled(db, it, Some(label), mod_path) | 331 | from_def_source_labeled(db, it, Some(label), mod_path) |
337 | } | 332 | } |
338 | Definition::Field(def) => { | 333 | Definition::Field(def) => { |
339 | let src = def.source(db).value; | 334 | #[allow(deprecated)] |
335 | let src = def.source(db)?.value; | ||
340 | if let FieldSource::Named(it) = src { | 336 | if let FieldSource::Named(it) = src { |
341 | from_def_source_labeled(db, def, it.short_label(), mod_path) | 337 | from_def_source_labeled(db, def, it.short_label(), mod_path) |
342 | } else { | 338 | } else { |
@@ -385,7 +381,8 @@ fn hover_for_definition(db: &RootDatabase, def: Definition) -> Option<Markup> { | |||
385 | D: HasSource<Ast = A> + HasAttrs + Copy, | 381 | D: HasSource<Ast = A> + HasAttrs + Copy, |
386 | A: ShortLabel, | 382 | A: ShortLabel, |
387 | { | 383 | { |
388 | let short_label = def.source(db).value.short_label(); | 384 | #[allow(deprecated)] |
385 | let short_label = def.source(db)?.value.short_label(); | ||
389 | from_def_source_labeled(db, def, short_label, mod_path) | 386 | from_def_source_labeled(db, def, short_label, mod_path) |
390 | } | 387 | } |
391 | 388 | ||
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs index b3331f03f..a450794f3 100644 --- a/crates/ide/src/lib.rs +++ b/crates/ide/src/lib.rs | |||
@@ -31,6 +31,7 @@ mod folding_ranges; | |||
31 | mod goto_definition; | 31 | mod goto_definition; |
32 | mod goto_implementation; | 32 | mod goto_implementation; |
33 | mod goto_type_definition; | 33 | mod goto_type_definition; |
34 | mod view_hir; | ||
34 | mod hover; | 35 | mod hover; |
35 | mod inlay_hints; | 36 | mod inlay_hints; |
36 | mod join_lines; | 37 | mod join_lines; |
@@ -271,6 +272,10 @@ impl Analysis { | |||
271 | self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range)) | 272 | self.with_db(|db| syntax_tree::syntax_tree(&db, file_id, text_range)) |
272 | } | 273 | } |
273 | 274 | ||
275 | pub fn view_hir(&self, position: FilePosition) -> Cancelable<String> { | ||
276 | self.with_db(|db| view_hir::view_hir(&db, position)) | ||
277 | } | ||
278 | |||
274 | pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> { | 279 | pub fn expand_macro(&self, position: FilePosition) -> Cancelable<Option<ExpandedMacro>> { |
275 | self.with_db(|db| expand_macro::expand_macro(db, position)) | 280 | self.with_db(|db| expand_macro::expand_macro(db, position)) |
276 | } | 281 | } |
diff --git a/crates/ide/src/view_hir.rs b/crates/ide/src/view_hir.rs new file mode 100644 index 000000000..cfcfb7cfb --- /dev/null +++ b/crates/ide/src/view_hir.rs | |||
@@ -0,0 +1,25 @@ | |||
1 | use hir::{Function, Semantics}; | ||
2 | use ide_db::base_db::FilePosition; | ||
3 | use ide_db::RootDatabase; | ||
4 | use syntax::{algo::find_node_at_offset, ast, AstNode}; | ||
5 | |||
6 | // Feature: View Hir | ||
7 | // | ||
8 | // |=== | ||
9 | // | Editor | Action Name | ||
10 | // | ||
11 | // | VS Code | **Rust Analyzer: View Hir** | ||
12 | // |=== | ||
13 | pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String { | ||
14 | body_hir(db, position).unwrap_or("Not inside a function body".to_string()) | ||
15 | } | ||
16 | |||
17 | fn body_hir(db: &RootDatabase, position: FilePosition) -> Option<String> { | ||
18 | let sema = Semantics::new(db); | ||
19 | let source_file = sema.parse(position.file_id); | ||
20 | |||
21 | let function = find_node_at_offset::<ast::Fn>(source_file.syntax(), position.offset)?; | ||
22 | |||
23 | let function: Function = sema.to_def(&function)?; | ||
24 | Some(function.debug_hir(db)) | ||
25 | } | ||
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs index ff10f71c3..436c59d2c 100644 --- a/crates/ide_db/src/search.rs +++ b/crates/ide_db/src/search.rs | |||
@@ -121,31 +121,56 @@ impl Definition { | |||
121 | 121 | ||
122 | if let Definition::Local(var) = self { | 122 | if let Definition::Local(var) = self { |
123 | let range = match var.parent(db) { | 123 | let range = match var.parent(db) { |
124 | DefWithBody::Function(f) => f.source(db).value.syntax().text_range(), | 124 | DefWithBody::Function(f) => { |
125 | DefWithBody::Const(c) => c.source(db).value.syntax().text_range(), | 125 | f.source(db).and_then(|src| Some(src.value.syntax().text_range())) |
126 | DefWithBody::Static(s) => s.source(db).value.syntax().text_range(), | 126 | } |
127 | DefWithBody::Const(c) => { | ||
128 | c.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
129 | } | ||
130 | DefWithBody::Static(s) => { | ||
131 | s.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
132 | } | ||
127 | }; | 133 | }; |
128 | let mut res = FxHashMap::default(); | 134 | let mut res = FxHashMap::default(); |
129 | res.insert(file_id, Some(range)); | 135 | res.insert(file_id, range); |
130 | return SearchScope::new(res); | 136 | return SearchScope::new(res); |
131 | } | 137 | } |
132 | 138 | ||
133 | if let Definition::LifetimeParam(param) = self { | 139 | if let Definition::LifetimeParam(param) = self { |
140 | #[allow(deprecated)] | ||
134 | let range = match param.parent(db) { | 141 | let range = match param.parent(db) { |
135 | hir::GenericDef::Function(it) => it.source(db).value.syntax().text_range(), | 142 | hir::GenericDef::Function(it) => { |
143 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
144 | } | ||
136 | hir::GenericDef::Adt(it) => match it { | 145 | hir::GenericDef::Adt(it) => match it { |
137 | hir::Adt::Struct(it) => it.source(db).value.syntax().text_range(), | 146 | hir::Adt::Struct(it) => { |
138 | hir::Adt::Union(it) => it.source(db).value.syntax().text_range(), | 147 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) |
139 | hir::Adt::Enum(it) => it.source(db).value.syntax().text_range(), | 148 | } |
149 | hir::Adt::Union(it) => { | ||
150 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
151 | } | ||
152 | hir::Adt::Enum(it) => { | ||
153 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
154 | } | ||
140 | }, | 155 | }, |
141 | hir::GenericDef::Trait(it) => it.source(db).value.syntax().text_range(), | 156 | hir::GenericDef::Trait(it) => { |
142 | hir::GenericDef::TypeAlias(it) => it.source(db).value.syntax().text_range(), | 157 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) |
143 | hir::GenericDef::Impl(it) => it.source(db).value.syntax().text_range(), | 158 | } |
144 | hir::GenericDef::Variant(it) => it.source(db).value.syntax().text_range(), | 159 | hir::GenericDef::TypeAlias(it) => { |
145 | hir::GenericDef::Const(it) => it.source(db).value.syntax().text_range(), | 160 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) |
161 | } | ||
162 | hir::GenericDef::Impl(it) => { | ||
163 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
164 | } | ||
165 | hir::GenericDef::Variant(it) => { | ||
166 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
167 | } | ||
168 | hir::GenericDef::Const(it) => { | ||
169 | it.source(db).and_then(|src| Some(src.value.syntax().text_range())) | ||
170 | } | ||
146 | }; | 171 | }; |
147 | let mut res = FxHashMap::default(); | 172 | let mut res = FxHashMap::default(); |
148 | res.insert(file_id, Some(range)); | 173 | res.insert(file_id, range); |
149 | return SearchScope::new(res); | 174 | return SearchScope::new(res); |
150 | } | 175 | } |
151 | 176 | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index a23fb7a33..9445aec07 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -161,11 +161,12 @@ impl AnalysisStatsCmd { | |||
161 | } | 161 | } |
162 | let mut msg = format!("processing: {}", full_name); | 162 | let mut msg = format!("processing: {}", full_name); |
163 | if verbosity.is_verbose() { | 163 | if verbosity.is_verbose() { |
164 | let src = f.source(db); | 164 | if let Some(src) = f.source(db) { |
165 | let original_file = src.file_id.original_file(db); | 165 | let original_file = src.file_id.original_file(db); |
166 | let path = vfs.file_path(original_file); | 166 | let path = vfs.file_path(original_file); |
167 | let syntax_range = src.value.syntax().text_range(); | 167 | let syntax_range = src.value.syntax().text_range(); |
168 | format_to!(msg, " ({} {:?})", path, syntax_range); | 168 | format_to!(msg, " ({} {:?})", path, syntax_range); |
169 | } | ||
169 | } | 170 | } |
170 | if verbosity.is_spammy() { | 171 | if verbosity.is_spammy() { |
171 | bar.println(msg.to_string()); | 172 | bar.println(msg.to_string()); |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 948cfc17c..dd486070b 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -105,6 +105,16 @@ pub(crate) fn handle_syntax_tree( | |||
105 | Ok(res) | 105 | Ok(res) |
106 | } | 106 | } |
107 | 107 | ||
108 | pub(crate) fn handle_view_hir( | ||
109 | snap: GlobalStateSnapshot, | ||
110 | params: lsp_types::TextDocumentPositionParams, | ||
111 | ) -> Result<String> { | ||
112 | let _p = profile::span("handle_view_hir"); | ||
113 | let position = from_proto::file_position(&snap, params)?; | ||
114 | let res = snap.analysis.view_hir(position)?; | ||
115 | Ok(res) | ||
116 | } | ||
117 | |||
108 | pub(crate) fn handle_expand_macro( | 118 | pub(crate) fn handle_expand_macro( |
109 | snap: GlobalStateSnapshot, | 119 | snap: GlobalStateSnapshot, |
110 | params: lsp_ext::ExpandMacroParams, | 120 | params: lsp_ext::ExpandMacroParams, |
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs index 93ac45415..a85978737 100644 --- a/crates/rust-analyzer/src/lsp_ext.rs +++ b/crates/rust-analyzer/src/lsp_ext.rs | |||
@@ -53,6 +53,14 @@ pub struct SyntaxTreeParams { | |||
53 | pub range: Option<Range>, | 53 | pub range: Option<Range>, |
54 | } | 54 | } |
55 | 55 | ||
56 | pub enum ViewHir {} | ||
57 | |||
58 | impl Request for ViewHir { | ||
59 | type Params = lsp_types::TextDocumentPositionParams; | ||
60 | type Result = String; | ||
61 | const METHOD: &'static str = "rust-analyzer/viewHir"; | ||
62 | } | ||
63 | |||
56 | pub enum ExpandMacro {} | 64 | pub enum ExpandMacro {} |
57 | 65 | ||
58 | impl Request for ExpandMacro { | 66 | impl Request for ExpandMacro { |
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs index 5d55dc96e..8eca79f7e 100644 --- a/crates/rust-analyzer/src/main_loop.rs +++ b/crates/rust-analyzer/src/main_loop.rs | |||
@@ -443,6 +443,7 @@ impl GlobalState { | |||
443 | .on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))? | 443 | .on_sync::<lsp_ext::MemoryUsage>(|s, p| handlers::handle_memory_usage(s, p))? |
444 | .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status) | 444 | .on::<lsp_ext::AnalyzerStatus>(handlers::handle_analyzer_status) |
445 | .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree) | 445 | .on::<lsp_ext::SyntaxTree>(handlers::handle_syntax_tree) |
446 | .on::<lsp_ext::ViewHir>(handlers::handle_view_hir) | ||
446 | .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro) | 447 | .on::<lsp_ext::ExpandMacro>(handlers::handle_expand_macro) |
447 | .on::<lsp_ext::ParentModule>(handlers::handle_parent_module) | 448 | .on::<lsp_ext::ParentModule>(handlers::handle_parent_module) |
448 | .on::<lsp_ext::Runnables>(handlers::handle_runnables) | 449 | .on::<lsp_ext::Runnables>(handlers::handle_runnables) |
diff --git a/docs/dev/README.md b/docs/dev/README.md index 4a2f9feb3..55527bab0 100644 --- a/docs/dev/README.md +++ b/docs/dev/README.md | |||
@@ -227,6 +227,8 @@ There are also two VS Code commands which might be of interest: | |||
227 | 227 | ||
228 | * `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection. | 228 | * `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection. |
229 | 229 | ||
230 | * `Rust Analyzer: View Hir` shows the HIR expressions within the function containing the cursor. | ||
231 | |||
230 | You can hover over syntax nodes in the opened text file to see the appropriate | 232 | You can hover over syntax nodes in the opened text file to see the appropriate |
231 | rust code that it refers to and the rust editor will also highlight the proper | 233 | rust code that it refers to and the rust editor will also highlight the proper |
232 | text range. | 234 | text range. |
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 8c01db07c..78d86f060 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md | |||
@@ -1,5 +1,5 @@ | |||
1 | <!--- | 1 | <!--- |
2 | lsp_ext.rs hash: 203fdf79b21b5987 | 2 | lsp_ext.rs hash: 91f2c62457e0a20f |
3 | 3 | ||
4 | If you need to change the above hash to make the test pass, please check if you | 4 | If you need to change the above hash to make the test pass, please check if you |
5 | need to adjust this doc as well and ping this issue: | 5 | need to adjust this doc as well and ping this issue: |
@@ -449,6 +449,17 @@ interface SyntaxTeeParams { | |||
449 | Returns textual representation of a parse tree for the file/selected region. | 449 | Returns textual representation of a parse tree for the file/selected region. |
450 | Primarily for debugging, but very useful for all people working on rust-analyzer itself. | 450 | Primarily for debugging, but very useful for all people working on rust-analyzer itself. |
451 | 451 | ||
452 | ## View Hir | ||
453 | |||
454 | **Method:** `rust-analyzer/viewHir` | ||
455 | |||
456 | **Request:** `TextDocumentPositionParams` | ||
457 | |||
458 | **Response:** `string` | ||
459 | |||
460 | Returns a textual representation of the HIR of the function containing the cursor. | ||
461 | For debugging or when working on rust-analyzer itself. | ||
462 | |||
452 | ## Expand Macro | 463 | ## Expand Macro |
453 | 464 | ||
454 | **Method:** `rust-analyzer/expandMacro` | 465 | **Method:** `rust-analyzer/expandMacro` |
diff --git a/editors/code/package.json b/editors/code/package.json index 587f11b90..3e55a3523 100644 --- a/editors/code/package.json +++ b/editors/code/package.json | |||
@@ -104,6 +104,11 @@ | |||
104 | "category": "Rust Analyzer" | 104 | "category": "Rust Analyzer" |
105 | }, | 105 | }, |
106 | { | 106 | { |
107 | "command": "rust-analyzer.viewHir", | ||
108 | "title": "View Hir", | ||
109 | "category": "Rust Analyzer" | ||
110 | }, | ||
111 | { | ||
107 | "command": "rust-analyzer.expandMacro", | 112 | "command": "rust-analyzer.expandMacro", |
108 | "title": "Expand macro recursively", | 113 | "title": "Expand macro recursively", |
109 | "category": "Rust Analyzer" | 114 | "category": "Rust Analyzer" |
@@ -1007,6 +1012,10 @@ | |||
1007 | "when": "inRustProject" | 1012 | "when": "inRustProject" |
1008 | }, | 1013 | }, |
1009 | { | 1014 | { |
1015 | "command": "rust-analyzer.viewHir", | ||
1016 | "when": "inRustProject" | ||
1017 | }, | ||
1018 | { | ||
1010 | "command": "rust-analyzer.expandMacro", | 1019 | "command": "rust-analyzer.expandMacro", |
1011 | "when": "inRustProject" | 1020 | "when": "inRustProject" |
1012 | }, | 1021 | }, |
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts index b12e134ca..c1c9f9754 100644 --- a/editors/code/src/commands.ts +++ b/editors/code/src/commands.ts | |||
@@ -340,6 +340,61 @@ export function syntaxTree(ctx: Ctx): Cmd { | |||
340 | }; | 340 | }; |
341 | } | 341 | } |
342 | 342 | ||
343 | // Opens the virtual file that will show the HIR of the function containing the cursor position | ||
344 | // | ||
345 | // The contents of the file come from the `TextDocumentContentProvider` | ||
346 | export function viewHir(ctx: Ctx): Cmd { | ||
347 | const tdcp = new class implements vscode.TextDocumentContentProvider { | ||
348 | readonly uri = vscode.Uri.parse('rust-analyzer://viewHir/hir.txt'); | ||
349 | readonly eventEmitter = new vscode.EventEmitter<vscode.Uri>(); | ||
350 | constructor() { | ||
351 | vscode.workspace.onDidChangeTextDocument(this.onDidChangeTextDocument, this, ctx.subscriptions); | ||
352 | vscode.window.onDidChangeActiveTextEditor(this.onDidChangeActiveTextEditor, this, ctx.subscriptions); | ||
353 | } | ||
354 | |||
355 | private onDidChangeTextDocument(event: vscode.TextDocumentChangeEvent) { | ||
356 | if (isRustDocument(event.document)) { | ||
357 | // We need to order this after language server updates, but there's no API for that. | ||
358 | // Hence, good old sleep(). | ||
359 | void sleep(10).then(() => this.eventEmitter.fire(this.uri)); | ||
360 | } | ||
361 | } | ||
362 | private onDidChangeActiveTextEditor(editor: vscode.TextEditor | undefined) { | ||
363 | if (editor && isRustEditor(editor)) { | ||
364 | this.eventEmitter.fire(this.uri); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | provideTextDocumentContent(_uri: vscode.Uri, ct: vscode.CancellationToken): vscode.ProviderResult<string> { | ||
369 | const rustEditor = ctx.activeRustEditor; | ||
370 | const client = ctx.client; | ||
371 | if (!rustEditor || !client) return ''; | ||
372 | |||
373 | const params = { | ||
374 | textDocument: client.code2ProtocolConverter.asTextDocumentIdentifier(rustEditor.document), | ||
375 | position: client.code2ProtocolConverter.asPosition( | ||
376 | rustEditor.selection.active, | ||
377 | ), | ||
378 | }; | ||
379 | return client.sendRequest(ra.viewHir, params, ct); | ||
380 | } | ||
381 | |||
382 | get onDidChange(): vscode.Event<vscode.Uri> { | ||
383 | return this.eventEmitter.event; | ||
384 | } | ||
385 | }; | ||
386 | |||
387 | ctx.pushCleanup(vscode.workspace.registerTextDocumentContentProvider('rust-analyzer', tdcp)); | ||
388 | |||
389 | return async () => { | ||
390 | const document = await vscode.workspace.openTextDocument(tdcp.uri); | ||
391 | tdcp.eventEmitter.fire(tdcp.uri); | ||
392 | void await vscode.window.showTextDocument(document, { | ||
393 | viewColumn: vscode.ViewColumn.Two, | ||
394 | preserveFocus: true | ||
395 | }); | ||
396 | }; | ||
397 | } | ||
343 | 398 | ||
344 | // Opens the virtual file that will show the syntax tree | 399 | // Opens the virtual file that will show the syntax tree |
345 | // | 400 | // |
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts index 5e877ce65..d21a3db86 100644 --- a/editors/code/src/lsp_ext.ts +++ b/editors/code/src/lsp_ext.ts | |||
@@ -24,6 +24,7 @@ export interface SyntaxTreeParams { | |||
24 | } | 24 | } |
25 | export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("rust-analyzer/syntaxTree"); | 25 | export const syntaxTree = new lc.RequestType<SyntaxTreeParams, string, void>("rust-analyzer/syntaxTree"); |
26 | 26 | ||
27 | export const viewHir = new lc.RequestType<lc.TextDocumentPositionParams, string, void>("rust-analyzer/viewHir"); | ||
27 | 28 | ||
28 | export interface ExpandMacroParams { | 29 | export interface ExpandMacroParams { |
29 | textDocument: lc.TextDocumentIdentifier; | 30 | textDocument: lc.TextDocumentIdentifier; |
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 282240d84..60907dfd4 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts | |||
@@ -105,6 +105,7 @@ async function tryActivate(context: vscode.ExtensionContext) { | |||
105 | ctx.registerCommand('joinLines', commands.joinLines); | 105 | ctx.registerCommand('joinLines', commands.joinLines); |
106 | ctx.registerCommand('parentModule', commands.parentModule); | 106 | ctx.registerCommand('parentModule', commands.parentModule); |
107 | ctx.registerCommand('syntaxTree', commands.syntaxTree); | 107 | ctx.registerCommand('syntaxTree', commands.syntaxTree); |
108 | ctx.registerCommand('viewHir', commands.viewHir); | ||
108 | ctx.registerCommand('expandMacro', commands.expandMacro); | 109 | ctx.registerCommand('expandMacro', commands.expandMacro); |
109 | ctx.registerCommand('run', commands.run); | 110 | ctx.registerCommand('run', commands.run); |
110 | ctx.registerCommand('debug', commands.debug); | 111 | ctx.registerCommand('debug', commands.debug); |