Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/hir-def/src/expr_store.rs2
-rw-r--r--crates/hir-def/src/expr_store/pretty.rs107
-rw-r--r--crates/hir/src/semantics.rs31
-rw-r--r--crates/hir/src/semantics/source_to_def.rs11
-rw-r--r--crates/hir/src/source_analyzer.rs12
-rw-r--r--crates/ide/src/view_hir.rs27
6 files changed, 146 insertions, 44 deletions
diff --git a/crates/hir-def/src/expr_store.rs b/crates/hir-def/src/expr_store.rs
index eb66e592d6..9349ee7740 100644
--- a/crates/hir-def/src/expr_store.rs
+++ b/crates/hir-def/src/expr_store.rs
@@ -4,7 +4,7 @@ pub mod body;
mod expander;
pub mod lower;
pub mod path;
-pub(crate) mod pretty;
+pub mod pretty;
pub mod scope;
#[cfg(test)]
mod tests;
diff --git a/crates/hir-def/src/expr_store/pretty.rs b/crates/hir-def/src/expr_store/pretty.rs
index 01476deb62..5e3580e590 100644
--- a/crates/hir-def/src/expr_store/pretty.rs
+++ b/crates/hir-def/src/expr_store/pretty.rs
@@ -10,8 +10,9 @@ use hir_expand::{Lookup, mod_path::PathKind};
use itertools::Itertools;
use span::Edition;
+use crate::signatures::StructFlags;
use crate::{
- DefWithBodyId, ItemTreeLoc, TypeParamId,
+ AdtId, DefWithBodyId, GenericDefId, ItemTreeLoc, TypeParamId, VariantId,
expr_store::path::{GenericArg, GenericArgs},
hir::{
Array, BindingAnnotation, CaptureBy, ClosureKind, Literal, Movability, Statement,
@@ -21,6 +22,7 @@ use crate::{
signatures::{FnFlags, FunctionSignature, StructSignature},
type_ref::{ConstRef, LifetimeRef, Mutability, TraitBoundModifier, TypeBound, UseArgRef},
};
+use crate::{item_tree::FieldsShape, signatures::FieldData};
use super::*;
@@ -40,13 +42,13 @@ macro_rules! wln {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub(crate) enum LineFormat {
+pub enum LineFormat {
Oneline,
Newline,
Indentation,
}
-pub(crate) fn print_body_hir(
+pub fn print_body_hir(
db: &dyn DefDatabase,
body: &Body,
owner: DefWithBodyId,
@@ -112,7 +114,93 @@ pub(crate) fn print_body_hir(
p.buf
}
-pub(crate) fn print_path(
+pub fn print_variant_body_hir(db: &dyn DefDatabase, owner: VariantId, edition: Edition) -> String {
+ let header = match owner {
+ VariantId::StructId(it) => {
+ it.lookup(db).id.resolved(db, |it| format!("struct {}", it.name.display(db, edition)))
+ }
+ VariantId::EnumVariantId(enum_variant_id) => {
+ let loc = enum_variant_id.lookup(db);
+ let enum_loc = loc.parent.lookup(db);
+ format!(
+ "enum {}::{}",
+ enum_loc.id.item_tree(db)[enum_loc.id.value].name.display(db, edition),
+ loc.id.item_tree(db)[loc.id.value].name.display(db, edition),
+ )
+ }
+ VariantId::UnionId(union_id) => union_id
+ .lookup(db)
+ .id
+ .resolved(db, |it| format!("union {}", it.name.display(db, edition))),
+ };
+
+ let fields = db.variant_fields(owner);
+
+ let mut p = Printer {
+ db,
+ store: &fields.store,
+ buf: header,
+ indent_level: 0,
+ line_format: LineFormat::Newline,
+ edition,
+ };
+ match fields.shape {
+ FieldsShape::Record => wln!(p, " {{"),
+ FieldsShape::Tuple => wln!(p, "("),
+ FieldsShape::Unit => (),
+ }
+
+ for (_, data) in fields.fields().iter() {
+ let FieldData { name, type_ref, visibility, is_unsafe } = data;
+ match visibility {
+ crate::item_tree::RawVisibility::Module(interned, _visibility_explicitness) => {
+ w!(p, "{}", interned.display(db, p.edition))
+ }
+ crate::item_tree::RawVisibility::Public => w!(p, "pub "),
+ }
+ if *is_unsafe {
+ w!(p, "unsafe ");
+ }
+ w!(p, "{}: ", name.display(db, p.edition));
+ p.print_type_ref(*type_ref);
+ }
+
+ match fields.shape {
+ FieldsShape::Record => wln!(p, "}}"),
+ FieldsShape::Tuple => wln!(p, ");"),
+ FieldsShape::Unit => wln!(p, ";"),
+ }
+ p.buf
+}
+
+pub fn print_signature(db: &dyn DefDatabase, owner: GenericDefId, edition: Edition) -> String {
+ match owner {
+ GenericDefId::AdtId(id) => match id {
+ AdtId::StructId(id) => {
+ let signature = db.struct_signature(id);
+ print_struct(db, &signature, edition)
+ }
+ AdtId::UnionId(id) => {
+ format!("unimplemented {id:?}")
+ }
+ AdtId::EnumId(id) => {
+ format!("unimplemented {id:?}")
+ }
+ },
+ GenericDefId::ConstId(id) => format!("unimplemented {id:?}"),
+ GenericDefId::FunctionId(id) => {
+ let signature = db.function_signature(id);
+ print_function(db, &signature, edition)
+ }
+ GenericDefId::ImplId(id) => format!("unimplemented {id:?}"),
+ GenericDefId::StaticId(id) => format!("unimplemented {id:?}"),
+ GenericDefId::TraitAliasId(id) => format!("unimplemented {id:?}"),
+ GenericDefId::TraitId(id) => format!("unimplemented {id:?}"),
+ GenericDefId::TypeAliasId(id) => format!("unimplemented {id:?}"),
+ }
+}
+
+pub fn print_path(
db: &dyn DefDatabase,
store: &ExpressionStore,
path: &Path,
@@ -130,14 +218,11 @@ pub(crate) fn print_path(
p.buf
}
-pub(crate) fn print_struct(
+pub fn print_struct(
db: &dyn DefDatabase,
StructSignature { name, generic_params, store, flags, shape, repr }: &StructSignature,
edition: Edition,
) -> String {
- use crate::item_tree::FieldsShape;
- use crate::signatures::StructFlags;
-
let mut p = Printer {
db,
store,
@@ -180,7 +265,7 @@ pub(crate) fn print_struct(
p.buf
}
-pub(crate) fn print_function(
+pub fn print_function(
db: &dyn DefDatabase,
FunctionSignature {
name,
@@ -342,7 +427,7 @@ fn print_generic_params(db: &dyn DefDatabase, generic_params: &GenericParams, p:
}
}
-pub(crate) fn print_expr_hir(
+pub fn print_expr_hir(
db: &dyn DefDatabase,
store: &ExpressionStore,
_owner: DefWithBodyId,
@@ -361,7 +446,7 @@ pub(crate) fn print_expr_hir(
p.buf
}
-pub(crate) fn print_pat_hir(
+pub fn print_pat_hir(
db: &dyn DefDatabase,
store: &ExpressionStore,
_owner: DefWithBodyId,
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 39130d1659..c0f99e09e3 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -20,7 +20,7 @@ use hir_def::{
type_ref::Mutability,
};
use hir_expand::{
- ExpandResult, FileRange, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
+ ExpandResult, FileRange, HirFileIdExt, InMacroFile, MacroCallId, MacroFileId, MacroFileIdExt,
attrs::collect_attrs,
builtin::{BuiltinFnLikeExpander, EagerExpander},
db::ExpandDatabase,
@@ -739,6 +739,35 @@ impl<'db> SemanticsImpl<'db> {
}
}
+ pub fn debug_hir_at(&self, token: SyntaxToken) -> Option<String> {
+ self.analyze_no_infer(&token.parent()?).and_then(|it| {
+ Some(match it.body_or_sig.as_ref()? {
+ crate::source_analyzer::BodyOrSig::Body { def, body, .. } => {
+ hir_def::expr_store::pretty::print_body_hir(
+ self.db,
+ body,
+ *def,
+ it.file_id.edition(self.db),
+ )
+ }
+ &crate::source_analyzer::BodyOrSig::VariantFields { def, .. } => {
+ hir_def::expr_store::pretty::print_variant_body_hir(
+ self.db,
+ def,
+ it.file_id.edition(self.db),
+ )
+ }
+ &crate::source_analyzer::BodyOrSig::Sig { def, .. } => {
+ hir_def::expr_store::pretty::print_signature(
+ self.db,
+ def,
+ it.file_id.edition(self.db),
+ )
+ }
+ })
+ })
+ }
+
/// Maps a node down by mapping its first and last token down.
pub fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
// This might not be the correct way to do this, but it works for now
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index 06100b30f8..2f06a1dc68 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -220,7 +220,7 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn module_to_def(&mut self, src: InFile<&ast::Module>) -> Option<ModuleId> {
let _p = tracing::info_span!("module_to_def").entered();
let parent_declaration = self
- .ancestors_with_macros(src.syntax_ref(), |_, ancestor, _| {
+ .parent_ancestors_with_macros(src.syntax_ref(), |_, ancestor, _| {
ancestor.map(Either::<ast::Module, ast::BlockExpr>::cast).transpose()
})
.map(|it| it.transpose());
@@ -519,7 +519,7 @@ impl SourceToDefCtx<'_, '_> {
pub(super) fn find_container(&mut self, src: InFile<&SyntaxNode>) -> Option<ChildContainer> {
let _p = tracing::info_span!("find_container").entered();
- let def = self.ancestors_with_macros(src, |this, container, child| {
+ let def = self.parent_ancestors_with_macros(src, |this, container, child| {
this.container_to_def(container, child)
});
if let Some(def) = def {
@@ -532,7 +532,7 @@ impl SourceToDefCtx<'_, '_> {
}
fn find_generic_param_container(&mut self, src: InFile<&SyntaxNode>) -> Option<GenericDefId> {
- self.ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
+ self.parent_ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
let item = ast::Item::cast(value)?;
match &item {
ast::Item::Fn(it) => this.fn_to_def(InFile::new(file_id, it)).map(Into::into),
@@ -555,7 +555,7 @@ impl SourceToDefCtx<'_, '_> {
// FIXME: Remove this when we do inference in signatures
fn find_pat_or_label_container(&mut self, src: InFile<&SyntaxNode>) -> Option<DefWithBodyId> {
- self.ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
+ self.parent_ancestors_with_macros(src, |this, InFile { file_id, value }, _| {
let item = match ast::Item::cast(value.clone()) {
Some(it) => it,
None => {
@@ -577,8 +577,7 @@ impl SourceToDefCtx<'_, '_> {
}
/// Skips the attributed item that caused the macro invocation we are climbing up
- ///
- fn ancestors_with_macros<T>(
+ fn parent_ancestors_with_macros<T>(
&mut self,
node: InFile<&SyntaxNode>,
mut cb: impl FnMut(
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 6a39f9cab8..b86fe1fa39 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -60,11 +60,11 @@ use triomphe::Arc;
pub(crate) struct SourceAnalyzer {
pub(crate) file_id: HirFileId,
pub(crate) resolver: Resolver,
- body_or_sig: Option<BodyOrSig>,
+ pub(crate) body_or_sig: Option<BodyOrSig>,
}
#[derive(Debug)]
-enum BodyOrSig {
+pub(crate) enum BodyOrSig {
Body {
def: DefWithBodyId,
body: Arc<Body>,
@@ -73,12 +73,12 @@ enum BodyOrSig {
},
// To be folded into body once it is considered one
VariantFields {
- _def: VariantId,
+ def: VariantId,
store: Arc<ExpressionStore>,
source_map: Arc<ExpressionStoreSourceMap>,
},
Sig {
- _def: GenericDefId,
+ def: GenericDefId,
store: Arc<ExpressionStore>,
source_map: Arc<ExpressionStoreSourceMap>,
// infer: Option<Arc<InferenceResult>>,
@@ -143,7 +143,7 @@ impl SourceAnalyzer {
let resolver = def.resolver(db);
SourceAnalyzer {
resolver,
- body_or_sig: Some(BodyOrSig::Sig { _def: def, store, source_map }),
+ body_or_sig: Some(BodyOrSig::Sig { def, store, source_map }),
file_id,
}
}
@@ -159,7 +159,7 @@ impl SourceAnalyzer {
SourceAnalyzer {
resolver,
body_or_sig: Some(BodyOrSig::VariantFields {
- _def: def,
+ def,
store: fields.store.clone(),
source_map,
}),
diff --git a/crates/ide/src/view_hir.rs b/crates/ide/src/view_hir.rs
index 954917d4c0..ec5e993f5a 100644
--- a/crates/ide/src/view_hir.rs
+++ b/crates/ide/src/view_hir.rs
@@ -1,6 +1,6 @@
-use hir::{DefWithBody, Semantics};
+use hir::Semantics;
use ide_db::{FilePosition, RootDatabase};
-use syntax::{AstNode, algo::ancestors_at_offset, ast};
+use syntax::AstNode;
// Feature: View Hir
//
@@ -10,21 +10,10 @@ use syntax::{AstNode, algo::ancestors_at_offset, ast};
//
// ![View Hir](https://user-images.githubusercontent.com/48062697/113065588-068bdb80-91b1-11eb-9a78-0b4ef1e972fb.gif)
pub(crate) fn view_hir(db: &RootDatabase, position: FilePosition) -> String {
- body_hir(db, position).unwrap_or_else(|| "Not inside a function body".to_owned())
-}
-
-fn body_hir(db: &RootDatabase, position: FilePosition) -> Option<String> {
- let sema = Semantics::new(db);
- let source_file = sema.parse_guess_edition(position.file_id);
-
- let item = ancestors_at_offset(source_file.syntax(), position.offset)
- .filter(|it| !ast::MacroCall::can_cast(it.kind()))
- .find_map(ast::Item::cast)?;
- let def: DefWithBody = match item {
- ast::Item::Fn(it) => sema.to_def(&it)?.into(),
- ast::Item::Const(it) => sema.to_def(&it)?.into(),
- ast::Item::Static(it) => sema.to_def(&it)?.into(),
- _ => return None,
- };
- Some(def.debug_hir(db))
+ (|| {
+ let sema = Semantics::new(db);
+ let source_file = sema.parse_guess_edition(position.file_id);
+ sema.debug_hir_at(source_file.syntax().token_at_offset(position.offset).next()?)
+ })()
+ .unwrap_or_else(|| "Not inside a lowerable item".to_owned())
}