Skip to content

Commit 121a12e

Browse files
authored
Merge pull request rust-lang#19573 from Veykril/push-swrzvrroornr
internal: Render sigantures with view hir command
2 parents f351279 + c970cac commit 121a12e

File tree

6 files changed

+146
-44
lines changed

6 files changed

+146
-44
lines changed

src/tools/rust-analyzer/crates/hir-def/src/expr_store.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ pub mod body;
44
mod expander;
55
pub mod lower;
66
pub mod path;
7-
pub(crate) mod pretty;
7+
pub mod pretty;
88
pub mod scope;
99
#[cfg(test)]
1010
mod tests;

src/tools/rust-analyzer/crates/hir-def/src/expr_store/pretty.rs

Lines changed: 96 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,9 @@ use hir_expand::{Lookup, mod_path::PathKind};
1010
use itertools::Itertools;
1111
use span::Edition;
1212

13+
use crate::signatures::StructFlags;
1314
use crate::{
14-
DefWithBodyId, ItemTreeLoc, TypeParamId,
15+
AdtId, DefWithBodyId, GenericDefId, ItemTreeLoc, TypeParamId, VariantId,
1516
expr_store::path::{GenericArg, GenericArgs},
1617
hir::{
1718
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement,
@@ -21,6 +22,7 @@ use crate::{
2122
signatures::{FnFlags, FunctionSignature, StructSignature},
2223
type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef},
2324
};
25+
use crate::{item_tree::FieldsShape, signatures::FieldData};
2426

2527
use super::*;
2628

@@ -40,13 +42,13 @@ macro_rules! wln {
4042
}
4143

4244
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
43-
pub(crate) enum LineFormat {
45+
pub enum LineFormat {
4446
Oneline,
4547
Newline,
4648
Indentation,
4749
}
4850

49-
pub(crate) fn print_body_hir(
51+
pub fn print_body_hir(
5052
db: &dyn DefDatabase,
5153
body: &Body,
5254
owner: DefWithBodyId,
@@ -112,7 +114,93 @@ pub(crate) fn print_body_hir(
112114
p.buf
113115
}
114116

115-
pub(crate) fn print_path(
117+
pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: Edition) -> String {
118+
let header = match owner {
119+
VariantId::StructId(it) => {
120+
it.lookup(db).id.resolved(db, |it| format!("struct {}", it.name.display(db, edition)))
121+
}
122+
VariantId::EnumVariantId(enum_variant_id) => {
123+
let loc = enum_variant_id.lookup(db);
124+
let enum_loc = loc.parent.lookup(db);
125+
format!(
126+
"enum {}::{}",
127+
enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition),
128+
loc.id.item_tree(db)[loc.id.value].name.display(db, edition),
129+
)
130+
}
131+
VariantId::UnionId(union_id) => union_id
132+
.lookup(db)
133+
.id
134+
.resolved(db, |it| format!("union {}", it.name.display(db, edition))),
135+
};
136+
137+
let fields = db.variant_fields(owner);
138+
139+
let mut p = Printer {
140+
db,
141+
store: &fields.store,
142+
buf: header,
143+
indent_level: 0,
144+
line_format: LineFormat::Newline,
145+
edition,
146+
};
147+
match fields.shape {
148+
FieldsShape::Record => wln!(p, " {{"),
149+
FieldsShape::Tuple => wln!(p, "("),
150+
FieldsShape::Unit => (),
151+
}
152+
153+
for (_, data) in fields.fields().iter() {
154+
let FieldData { name, type_ref, visibility, is_unsafe } = data;
155+
match visibility {
156+
crate::item_tree::RawVisibility::Module(interned, _visibility_explicitness) => {
157+
w!(p, "{}", interned.display(db, p.edition))
158+
}
159+
crate::item_tree::RawVisibility::Public => w!(p, "pub "),
160+
}
161+
if *is_unsafe {
162+
w!(p, "unsafe ");
163+
}
164+
w!(p, "{}: ", name.display(db, p.edition));
165+
p.print_type_ref(*type_ref);
166+
}
167+
168+
match fields.shape {
169+
FieldsShape::Record => wln!(p, "}}"),
170+
FieldsShape::Tuple => wln!(p, ");"),
171+
FieldsShape::Unit => wln!(p, ";"),
172+
}
173+
p.buf
174+
}
175+
176+
pub fn print_signature(db: &dyn DefDatabase, owner: GenericDefId, edition: Edition) -> String {
177+
match owner {
178+
GenericDefId::AdtId(id) => match id {
179+
AdtId::StructId(id) => {
180+
let signature = db.struct_signature(id);
181+
print_struct(db, &signature, edition)
182+
}
183+
AdtId::UnionId(id) => {
184+
format!("unimplemented {id:?}")
185+
}
186+
AdtId::EnumId(id) => {
187+
format!("unimplemented {id:?}")
188+
}
189+
},
190+
GenericDefId::ConstId(id) => format!("unimplemented {id:?}"),
191+
GenericDefId::FunctionId(id) => {
192+
let signature = db.function_signature(id);
193+
print_function(db, &signature, edition)
194+
}
195+
GenericDefId::ImplId(id) => format!("unimplemented {id:?}"),
196+
GenericDefId::StaticId(id) => format!("unimplemented {id:?}"),
197+
GenericDefId::TraitAliasId(id) => format!("unimplemented {id:?}"),
198+
GenericDefId::TraitId(id) => format!("unimplemented {id:?}"),
199+
GenericDefId::TypeAliasId(id) => format!("unimplemented {id:?}"),
200+
}
201+
}
202+
203+
pub fn print_path(
116204
db: &dyn DefDatabase,
117205
store: &ExpressionStore,
118206
path: &Path,
@@ -130,14 +218,11 @@ pub(crate) fn print_path(
130218
p.buf
131219
}
132220

133-
pub(crate) fn print_struct(
221+
pub fn print_struct(
134222
db: &dyn DefDatabase,
135223
StructSignature { name, generic_params, store, flags, shape, repr }: &StructSignature,
136224
edition: Edition,
137225
) -> String {
138-
use crate::item_tree::FieldsShape;
139-
use crate::signatures::StructFlags;
140-
141226
let mut p = Printer {
142227
db,
143228
store,
@@ -180,7 +265,7 @@ pub(crate) fn print_struct(
180265
p.buf
181266
}
182267

183-
pub(crate) fn print_function(
268+
pub fn print_function(
184269
db: &dyn DefDatabase,
185270
FunctionSignature {
186271
name,
@@ -342,7 +427,7 @@ fn print_generic_params(db: &dyn DefDatabase, generic_params: &GenericParams, p:
342427
}
343428
}
344429

345-
pub(crate) fn print_expr_hir(
430+
pub fn print_expr_hir(
346431
db: &dyn DefDatabase,
347432
store: &ExpressionStore,
348433
_owner: DefWithBodyId,
@@ -361,7 +446,7 @@ pub(crate) fn print_expr_hir(
361446
p.buf
362447
}
363448

364-
pub(crate) fn print_pat_hir(
449+
pub fn print_pat_hir(
365450
db: &dyn DefDatabase,
366451
store: &ExpressionStore,
367452
_owner: DefWithBodyId,

src/tools/rust-analyzer/crates/hir/src/semantics.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use hir_def::{
2020
type_ref::Mutability,
2121
};
2222
use hir_expand::{
23-
ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
23+
ExpandResult, FileRange, HirFileIdExt, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
2424
attrs::collect_attrs,
2525
builtin::{BuiltinFnLikeExpander, EagerExpander},
2626
db::ExpandDatabase,
@@ -739,6 +739,35 @@ impl<'db> SemanticsImpl<'db> {
739739
}
740740
}
741741

742+
pub fn debug_hir_at(&self, token: SyntaxToken) -> Option<String> {
743+
self.analyze_no_infer(&token.parent()?).and_then(|it| {
744+
Some(match it.body_or_sig.as_ref()? {
745+
crate::source_analyzer::BodyOrSig::Body { def, body, .. } => {
746+
hir_def::expr_store::pretty::print_body_hir(
747+
self.db,
748+
body,
749+
*def,
750+
it.file_id.edition(self.db),
751+
)
752+
}
753+
&crate::source_analyzer::BodyOrSig::VariantFields { def, .. } => {
754+
hir_def::expr_store::pretty::print_variant_body_hir(
755+
self.db,
756+
def,
757+
it.file_id.edition(self.db),
758+
)
759+
}
760+
&crate::source_analyzer::BodyOrSig::Sig { def, .. } => {
761+
hir_def::expr_store::pretty::print_signature(
762+
self.db,
763+
def,
764+
it.file_id.edition(self.db),
765+
)
766+
}
767+
})
768+
})
769+
}
770+
742771
/// Maps a node down by mapping its first and last token down.
743772
pub fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
744773
// This might not be the correct way to do this, but it works for now

src/tools/rust-analyzer/crates/hir/src/semantics/source_to_def.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ impl SourceToDefCtx<'_, '_> {
220220
pub(super) fn module_to_def(&mut self, src: InFile<&ast::Module>) -> Option<ModuleId> {
221221
let _p = tracing::info_span!("module_to_def").entered();
222222
let parent_declaration = self
223-
.ancestors_with_macros(src.syntax_ref(), |_, ancestor, _| {
223+
.parent_ancestors_with_macros(src.syntax_ref(), |_, ancestor, _| {
224224
ancestor.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose()
225225
})
226226
.map(|it| it.transpose());
@@ -519,7 +519,7 @@ impl SourceToDefCtx<'_, '_> {
519519

520520
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
521521
let _p = tracing::info_span!("find_container").entered();
522-
let def = self.ancestors_with_macros(src, |this, container, child| {
522+
let def = self.parent_ancestors_with_macros(src, |this, container, child| {
523523
this.container_to_def(container, child)
524524
});
525525
if let Some(def) = def {
@@ -532,7 +532,7 @@ impl SourceToDefCtx<'_, '_> {
532532
}
533533

534534
fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
535-
self.ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
535+
self.parent_ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
536536
let item = ast::Item::cast(value)?;
537537
match &item {
538538
ast::Item::Fn(it) => this.fn_to_def(InFile::new(file_id, it)).map(Into::into),
@@ -555,7 +555,7 @@ impl SourceToDefCtx<'_, '_> {
555555

556556
// FIXME: Remove this when we do inference in signatures
557557
fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
558-
self.ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
558+
self.parent_ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
559559
let item = match ast::Item::cast(value.clone()) {
560560
Some(it) => it,
561561
None => {
@@ -577,8 +577,7 @@ impl SourceToDefCtx<'_, '_> {
577577
}
578578

579579
/// Skips the attributed item that caused the macro invocation we are climbing up
580-
///
581-
fn ancestors_with_macros<T>(
580+
fn parent_ancestors_with_macros<T>(
582581
&mut self,
583582
node: InFile<&SyntaxNode>,
584583
mut cb: impl FnMut(

src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,11 @@ use triomphe::Arc;
6060
pub(crate) struct SourceAnalyzer {
6161
pub(crate) file_id: HirFileId,
6262
pub(crate) resolver: Resolver,
63-
body_or_sig: Option<BodyOrSig>,
63+
pub(crate) body_or_sig: Option<BodyOrSig>,
6464
}
6565

6666
#[derive(Debug)]
67-
enum BodyOrSig {
67+
pub(crate) enum BodyOrSig {
6868
Body {
6969
def: DefWithBodyId,
7070
body: Arc<Body>,
@@ -73,12 +73,12 @@ enum BodyOrSig {
7373
},
7474
// To be folded into body once it is considered one
7575
VariantFields {
76-
_def: VariantId,
76+
def: VariantId,
7777
store: Arc<ExpressionStore>,
7878
source_map: Arc<ExpressionStoreSourceMap>,
7979
},
8080
Sig {
81-
_def: GenericDefId,
81+
def: GenericDefId,
8282
store: Arc<ExpressionStore>,
8383
source_map: Arc<ExpressionStoreSourceMap>,
8484
// infer: Option<Arc<InferenceResult>>,
@@ -143,7 +143,7 @@ impl SourceAnalyzer {
143143
let resolver = def.resolver(db);
144144
SourceAnalyzer {
145145
resolver,
146-
body_or_sig: Some(BodyOrSig::Sig { _def: def, store, source_map }),
146+
body_or_sig: Some(BodyOrSig::Sig { def, store, source_map }),
147147
file_id,
148148
}
149149
}
@@ -159,7 +159,7 @@ impl SourceAnalyzer {
159159
SourceAnalyzer {
160160
resolver,
161161
body_or_sig: Some(BodyOrSig::VariantFields {
162-
_def: def,
162+
def,
163163
store: fields.store.clone(),
164164
source_map,
165165
}),
Lines changed: 8 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
use hir::{DefWithBody, Semantics};
1+
use hir::Semantics;
22
use ide_db::{FilePosition, RootDatabase};
3-
use syntax::{AstNode, algo::ancestors_at_offset, ast};
3+
use syntax::AstNode;
44

55
// Feature: View Hir
66
//
@@ -10,21 +10,10 @@ use syntax::{AstNode, algo::ancestors_at_offset, ast};
1010
//
1111
// ![View Hir](https://user-images.githubusercontent.com/48062697/113065588-068bdb80-91b1-11eb-9a78-0b4ef1e972fb.gif)
1212
pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String {
13-
body_hir(db, position).unwrap_or_else(|| "Not inside a function body".to_owned())
14-
}
15-
16-
fn body_hir(db: &RootDatabase, position: FilePosition) -> Option<String> {
17-
let sema = Semantics::new(db);
18-
let source_file = sema.parse_guess_edition(position.file_id);
19-
20-
let item = ancestors_at_offset(source_file.syntax(), position.offset)
21-
.filter(|it| !ast::MacroCall::can_cast(it.kind()))
22-
.find_map(ast::Item::cast)?;
23-
let def: DefWithBody = match item {
24-
ast::Item::Fn(it) => sema.to_def(&it)?.into(),
25-
ast::Item::Const(it) => sema.to_def(&it)?.into(),
26-
ast::Item::Static(it) => sema.to_def(&it)?.into(),
27-
_ => return None,
28-
};
29-
Some(def.debug_hir(db))
13+
(|| {
14+
let sema = Semantics::new(db);
15+
let source_file = sema.parse_guess_edition(position.file_id);
16+
sema.debug_hir_at(source_file.syntax().token_at_offset(position.offset).next()?)
17+
})()
18+
.unwrap_or_else(|| "Not inside a lowerable item".to_owned())
3019
}

0 commit comments

Comments
 (0)