hir_def/expr_store/
body.rs1use std::ops;
4
5use hir_expand::{InFile, Lookup};
6use span::Edition;
7use syntax::ast;
8use triomphe::Arc;
9
10use crate::{
11 DefWithBodyId, HasModule,
12 db::DefDatabase,
13 expr_store::{
14 ExpressionStore, ExpressionStoreSourceMap, SelfParamPtr, lower::lower_body, pretty,
15 },
16 hir::{BindingId, ExprId, PatId},
17 src::HasSource,
18};
19
20#[derive(Debug, Eq, PartialEq)]
22pub struct Body {
23 pub store: ExpressionStore,
24 pub params: Box<[PatId]>,
31 pub self_param: Option<BindingId>,
32 pub body_expr: ExprId,
34}
35
36impl ops::Deref for Body {
37 type Target = ExpressionStore;
38
39 #[inline]
40 fn deref(&self) -> &Self::Target {
41 &self.store
42 }
43}
44
45#[derive(Default, Debug, Eq, PartialEq)]
57pub struct BodySourceMap {
58 pub self_param: Option<InFile<SelfParamPtr>>,
59 pub store: ExpressionStoreSourceMap,
60}
61
62impl ops::Deref for BodySourceMap {
63 type Target = ExpressionStoreSourceMap;
64
65 #[inline]
66 fn deref(&self) -> &Self::Target {
67 &self.store
68 }
69}
70
71impl Body {
72 pub(crate) fn body_with_source_map_query(
73 db: &dyn DefDatabase,
74 def: DefWithBodyId,
75 ) -> (Arc<Body>, Arc<BodySourceMap>) {
76 let _p = tracing::info_span!("body_with_source_map_query").entered();
77 let mut params = None;
78
79 let mut is_async_fn = false;
80 let InFile { file_id, value: body } = {
81 match def {
82 DefWithBodyId::FunctionId(f) => {
83 let f = f.lookup(db);
84 let src = f.source(db);
85 params = src.value.param_list();
86 is_async_fn = src.value.async_token().is_some();
87 src.map(|it| it.body().map(ast::Expr::from))
88 }
89 DefWithBodyId::ConstId(c) => {
90 let c = c.lookup(db);
91 let src = c.source(db);
92 src.map(|it| it.body())
93 }
94 DefWithBodyId::StaticId(s) => {
95 let s = s.lookup(db);
96 let src = s.source(db);
97 src.map(|it| it.body())
98 }
99 DefWithBodyId::VariantId(v) => {
100 let s = v.lookup(db);
101 let src = s.source(db);
102 src.map(|it| it.expr())
103 }
104 }
105 };
106 let module = def.module(db);
107 let (body, source_map) = lower_body(db, def, file_id, module, params, body, is_async_fn);
108
109 (Arc::new(body), Arc::new(source_map))
110 }
111
112 pub(crate) fn body_query(db: &dyn DefDatabase, def: DefWithBodyId) -> Arc<Body> {
113 db.body_with_source_map(def).0
114 }
115
116 pub fn pretty_print(
117 &self,
118 db: &dyn DefDatabase,
119 owner: DefWithBodyId,
120 edition: Edition,
121 ) -> String {
122 pretty::print_body_hir(db, self, owner, edition)
123 }
124
125 pub fn pretty_print_expr(
126 &self,
127 db: &dyn DefDatabase,
128 owner: DefWithBodyId,
129 expr: ExprId,
130 edition: Edition,
131 ) -> String {
132 pretty::print_expr_hir(db, self, owner, expr, edition)
133 }
134
135 pub fn pretty_print_pat(
136 &self,
137 db: &dyn DefDatabase,
138 owner: DefWithBodyId,
139 pat: PatId,
140 oneline: bool,
141 edition: Edition,
142 ) -> String {
143 pretty::print_pat_hir(db, self, owner, pat, oneline, edition)
144 }
145}
146
147impl BodySourceMap {
148 pub fn self_param_syntax(&self) -> Option<InFile<SelfParamPtr>> {
149 self.self_param
150 }
151}