aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def/src')
-rw-r--r--crates/ra_hir_def/src/attr.rs8
-rw-r--r--crates/ra_hir_def/src/body/lower.rs68
-rw-r--r--crates/ra_hir_def/src/body/scope.rs4
-rw-r--r--crates/ra_hir_def/src/data.rs6
-rw-r--r--crates/ra_hir_def/src/docs.rs50
-rw-r--r--crates/ra_hir_def/src/expr.rs19
6 files changed, 131 insertions, 24 deletions
diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs
index 8b6c0bede..2eeba0572 100644
--- a/crates/ra_hir_def/src/attr.rs
+++ b/crates/ra_hir_def/src/attr.rs
@@ -87,12 +87,18 @@ impl Attrs {
87 } 87 }
88 88
89 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { 89 pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
90 let docs = ast::CommentIter::from_syntax_node(owner.syntax()).doc_comment_text().map(
91 |docs_text| Attr {
92 input: Some(AttrInput::Literal(SmolStr::new(docs_text))),
93 path: ModPath::from(hir_expand::name!(doc)),
94 },
95 );
90 let mut attrs = owner.attrs().peekable(); 96 let mut attrs = owner.attrs().peekable();
91 let entries = if attrs.peek().is_none() { 97 let entries = if attrs.peek().is_none() {
92 // Avoid heap allocation 98 // Avoid heap allocation
93 None 99 None
94 } else { 100 } else {
95 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).collect()) 101 Some(attrs.flat_map(|ast| Attr::from_src(ast, hygiene)).chain(docs).collect())
96 }; 102 };
97 Attrs { entries } 103 Attrs { entries }
98 } 104 }
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs
index 905c0cf5d..f159f80af 100644
--- a/crates/ra_hir_def/src/body/lower.rs
+++ b/crates/ra_hir_def/src/body/lower.rs
@@ -134,7 +134,7 @@ impl ExprCollector<'_> {
134 self.make_expr(expr, Err(SyntheticSyntax)) 134 self.make_expr(expr, Err(SyntheticSyntax))
135 } 135 }
136 fn empty_block(&mut self) -> ExprId { 136 fn empty_block(&mut self) -> ExprId {
137 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None }) 137 self.alloc_expr_desugared(Expr::Block { statements: Vec::new(), tail: None, label: None })
138 } 138 }
139 fn missing_expr(&mut self) -> ExprId { 139 fn missing_expr(&mut self) -> ExprId {
140 self.alloc_expr_desugared(Expr::Missing) 140 self.alloc_expr_desugared(Expr::Missing)
@@ -215,7 +215,16 @@ impl ExprCollector<'_> {
215 ast::Expr::BlockExpr(e) => self.collect_block(e), 215 ast::Expr::BlockExpr(e) => self.collect_block(e),
216 ast::Expr::LoopExpr(e) => { 216 ast::Expr::LoopExpr(e) => {
217 let body = self.collect_block_opt(e.loop_body()); 217 let body = self.collect_block_opt(e.loop_body());
218 self.alloc_expr(Expr::Loop { body }, syntax_ptr) 218 self.alloc_expr(
219 Expr::Loop {
220 body,
221 label: e
222 .label()
223 .and_then(|l| l.lifetime_token())
224 .map(|l| Name::new_lifetime(&l)),
225 },
226 syntax_ptr,
227 )
219 } 228 }
220 ast::Expr::WhileExpr(e) => { 229 ast::Expr::WhileExpr(e) => {
221 let body = self.collect_block_opt(e.loop_body()); 230 let body = self.collect_block_opt(e.loop_body());
@@ -230,25 +239,56 @@ impl ExprCollector<'_> {
230 let pat = self.collect_pat(pat); 239 let pat = self.collect_pat(pat);
231 let match_expr = self.collect_expr_opt(condition.expr()); 240 let match_expr = self.collect_expr_opt(condition.expr());
232 let placeholder_pat = self.missing_pat(); 241 let placeholder_pat = self.missing_pat();
233 let break_ = self.alloc_expr_desugared(Expr::Break { expr: None }); 242 let break_ =
243 self.alloc_expr_desugared(Expr::Break { expr: None, label: None });
234 let arms = vec![ 244 let arms = vec![
235 MatchArm { pat, expr: body, guard: None }, 245 MatchArm { pat, expr: body, guard: None },
236 MatchArm { pat: placeholder_pat, expr: break_, guard: None }, 246 MatchArm { pat: placeholder_pat, expr: break_, guard: None },
237 ]; 247 ];
238 let match_expr = 248 let match_expr =
239 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms }); 249 self.alloc_expr_desugared(Expr::Match { expr: match_expr, arms });
240 return self.alloc_expr(Expr::Loop { body: match_expr }, syntax_ptr); 250 return self.alloc_expr(
251 Expr::Loop {
252 body: match_expr,
253 label: e
254 .label()
255 .and_then(|l| l.lifetime_token())
256 .map(|l| Name::new_lifetime(&l)),
257 },
258 syntax_ptr,
259 );
241 } 260 }
242 }, 261 },
243 }; 262 };
244 263
245 self.alloc_expr(Expr::While { condition, body }, syntax_ptr) 264 self.alloc_expr(
265 Expr::While {
266 condition,
267 body,
268 label: e
269 .label()
270 .and_then(|l| l.lifetime_token())
271 .map(|l| Name::new_lifetime(&l)),
272 },
273 syntax_ptr,
274 )
246 } 275 }
247 ast::Expr::ForExpr(e) => { 276 ast::Expr::ForExpr(e) => {
248 let iterable = self.collect_expr_opt(e.iterable()); 277 let iterable = self.collect_expr_opt(e.iterable());
249 let pat = self.collect_pat_opt(e.pat()); 278 let pat = self.collect_pat_opt(e.pat());
250 let body = self.collect_block_opt(e.loop_body()); 279 let body = self.collect_block_opt(e.loop_body());
251 self.alloc_expr(Expr::For { iterable, pat, body }, syntax_ptr) 280 self.alloc_expr(
281 Expr::For {
282 iterable,
283 pat,
284 body,
285 label: e
286 .label()
287 .and_then(|l| l.lifetime_token())
288 .map(|l| Name::new_lifetime(&l)),
289 },
290 syntax_ptr,
291 )
252 } 292 }
253 ast::Expr::CallExpr(e) => { 293 ast::Expr::CallExpr(e) => {
254 let callee = self.collect_expr_opt(e.expr()); 294 let callee = self.collect_expr_opt(e.expr());
@@ -301,13 +341,16 @@ impl ExprCollector<'_> {
301 .unwrap_or(Expr::Missing); 341 .unwrap_or(Expr::Missing);
302 self.alloc_expr(path, syntax_ptr) 342 self.alloc_expr(path, syntax_ptr)
303 } 343 }
304 ast::Expr::ContinueExpr(_e) => { 344 ast::Expr::ContinueExpr(e) => self.alloc_expr(
305 // FIXME: labels 345 Expr::Continue { label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
306 self.alloc_expr(Expr::Continue, syntax_ptr) 346 syntax_ptr,
307 } 347 ),
308 ast::Expr::BreakExpr(e) => { 348 ast::Expr::BreakExpr(e) => {
309 let expr = e.expr().map(|e| self.collect_expr(e)); 349 let expr = e.expr().map(|e| self.collect_expr(e));
310 self.alloc_expr(Expr::Break { expr }, syntax_ptr) 350 self.alloc_expr(
351 Expr::Break { expr, label: e.lifetime_token().map(|l| Name::new_lifetime(&l)) },
352 syntax_ptr,
353 )
311 } 354 }
312 ast::Expr::ParenExpr(e) => { 355 ast::Expr::ParenExpr(e) => {
313 let inner = self.collect_expr_opt(e.expr()); 356 let inner = self.collect_expr_opt(e.expr());
@@ -529,7 +572,8 @@ impl ExprCollector<'_> {
529 }) 572 })
530 .collect(); 573 .collect();
531 let tail = block.expr().map(|e| self.collect_expr(e)); 574 let tail = block.expr().map(|e| self.collect_expr(e));
532 self.alloc_expr(Expr::Block { statements, tail }, syntax_node_ptr) 575 let label = block.label().and_then(|l| l.lifetime_token()).map(|t| Name::new_lifetime(&t));
576 self.alloc_expr(Expr::Block { statements, tail, label }, syntax_node_ptr)
533 } 577 }
534 578
535 fn collect_block_items(&mut self, block: &ast::BlockExpr) { 579 fn collect_block_items(&mut self, block: &ast::BlockExpr) {
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 09e92b74e..e48ff38f9 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -138,10 +138,10 @@ fn compute_block_scopes(
138fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) { 138fn compute_expr_scopes(expr: ExprId, body: &Body, scopes: &mut ExprScopes, scope: ScopeId) {
139 scopes.set_scope(expr, scope); 139 scopes.set_scope(expr, scope);
140 match &body[expr] { 140 match &body[expr] {
141 Expr::Block { statements, tail } => { 141 Expr::Block { statements, tail, .. } => {
142 compute_block_scopes(&statements, *tail, body, scopes, scope); 142 compute_block_scopes(&statements, *tail, body, scopes, scope);
143 } 143 }
144 Expr::For { iterable, pat, body: body_expr } => { 144 Expr::For { iterable, pat, body: body_expr, .. } => {
145 compute_expr_scopes(*iterable, body, scopes, scope); 145 compute_expr_scopes(*iterable, body, scopes, scope);
146 let scope = scopes.new_scope(scope); 146 let scope = scopes.new_scope(scope);
147 scopes.add_bindings(body, scope, *pat); 147 scopes.add_bindings(body, scope, *pat);
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index e2130d931..807195d25 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -34,6 +34,7 @@ pub struct FunctionData {
34 /// True if the first param is `self`. This is relevant to decide whether this 34 /// True if the first param is `self`. This is relevant to decide whether this
35 /// can be called as a method. 35 /// can be called as a method.
36 pub has_self_param: bool, 36 pub has_self_param: bool,
37 pub is_unsafe: bool,
37 pub visibility: RawVisibility, 38 pub visibility: RawVisibility,
38} 39}
39 40
@@ -85,11 +86,14 @@ impl FunctionData {
85 ret_type 86 ret_type
86 }; 87 };
87 88
89 let is_unsafe = src.value.unsafe_token().is_some();
90
88 let vis_default = RawVisibility::default_for_container(loc.container); 91 let vis_default = RawVisibility::default_for_container(loc.container);
89 let visibility = 92 let visibility =
90 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility())); 93 RawVisibility::from_ast_with_default(db, vis_default, src.map(|s| s.visibility()));
91 94
92 let sig = FunctionData { name, params, ret_type, has_self_param, visibility, attrs }; 95 let sig =
96 FunctionData { name, params, ret_type, has_self_param, is_unsafe, visibility, attrs };
93 Arc::new(sig) 97 Arc::new(sig)
94 } 98 }
95} 99}
diff --git a/crates/ra_hir_def/src/docs.rs b/crates/ra_hir_def/src/docs.rs
index b221ae1ce..2630b3d89 100644
--- a/crates/ra_hir_def/src/docs.rs
+++ b/crates/ra_hir_def/src/docs.rs
@@ -29,6 +29,13 @@ impl Documentation {
29 Documentation(s.into()) 29 Documentation(s.into())
30 } 30 }
31 31
32 pub fn from_ast<N>(node: &N) -> Option<Documentation>
33 where
34 N: ast::DocCommentsOwner + ast::AttrsOwner,
35 {
36 docs_from_ast(node)
37 }
38
32 pub fn as_str(&self) -> &str { 39 pub fn as_str(&self) -> &str {
33 &*self.0 40 &*self.0
34 } 41 }
@@ -70,6 +77,45 @@ impl Documentation {
70 } 77 }
71} 78}
72 79
73pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> { 80pub(crate) fn docs_from_ast<N>(node: &N) -> Option<Documentation>
74 node.doc_comment_text().map(|it| Documentation::new(&it)) 81where
82 N: ast::DocCommentsOwner + ast::AttrsOwner,
83{
84 let doc_comment_text = node.doc_comment_text();
85 let doc_attr_text = expand_doc_attrs(node);
86 let docs = merge_doc_comments_and_attrs(doc_comment_text, doc_attr_text);
87 docs.map(|it| Documentation::new(&it))
88}
89
90fn merge_doc_comments_and_attrs(
91 doc_comment_text: Option<String>,
92 doc_attr_text: Option<String>,
93) -> Option<String> {
94 match (doc_comment_text, doc_attr_text) {
95 (Some(mut comment_text), Some(attr_text)) => {
96 comment_text.push_str("\n\n");
97 comment_text.push_str(&attr_text);
98 Some(comment_text)
99 }
100 (Some(comment_text), None) => Some(comment_text),
101 (None, Some(attr_text)) => Some(attr_text),
102 (None, None) => None,
103 }
104}
105
106fn expand_doc_attrs(owner: &dyn ast::AttrsOwner) -> Option<String> {
107 let mut docs = String::new();
108 for attr in owner.attrs() {
109 if let Some(("doc", value)) =
110 attr.as_simple_key_value().as_ref().map(|(k, v)| (k.as_str(), v.as_str()))
111 {
112 docs.push_str(value);
113 docs.push_str("\n\n");
114 }
115 }
116 if docs.is_empty() {
117 None
118 } else {
119 Some(docs.trim_end_matches("\n\n").to_owned())
120 }
75} 121}
diff --git a/crates/ra_hir_def/src/expr.rs b/crates/ra_hir_def/src/expr.rs
index f25c6f958..ca49b26d1 100644
--- a/crates/ra_hir_def/src/expr.rs
+++ b/crates/ra_hir_def/src/expr.rs
@@ -52,18 +52,22 @@ pub enum Expr {
52 Block { 52 Block {
53 statements: Vec<Statement>, 53 statements: Vec<Statement>,
54 tail: Option<ExprId>, 54 tail: Option<ExprId>,
55 label: Option<Name>,
55 }, 56 },
56 Loop { 57 Loop {
57 body: ExprId, 58 body: ExprId,
59 label: Option<Name>,
58 }, 60 },
59 While { 61 While {
60 condition: ExprId, 62 condition: ExprId,
61 body: ExprId, 63 body: ExprId,
64 label: Option<Name>,
62 }, 65 },
63 For { 66 For {
64 iterable: ExprId, 67 iterable: ExprId,
65 pat: PatId, 68 pat: PatId,
66 body: ExprId, 69 body: ExprId,
70 label: Option<Name>,
67 }, 71 },
68 Call { 72 Call {
69 callee: ExprId, 73 callee: ExprId,
@@ -79,9 +83,12 @@ pub enum Expr {
79 expr: ExprId, 83 expr: ExprId,
80 arms: Vec<MatchArm>, 84 arms: Vec<MatchArm>,
81 }, 85 },
82 Continue, 86 Continue {
87 label: Option<Name>,
88 },
83 Break { 89 Break {
84 expr: Option<ExprId>, 90 expr: Option<ExprId>,
91 label: Option<Name>,
85 }, 92 },
86 Return { 93 Return {
87 expr: Option<ExprId>, 94 expr: Option<ExprId>,
@@ -225,7 +232,7 @@ impl Expr {
225 f(*else_branch); 232 f(*else_branch);
226 } 233 }
227 } 234 }
228 Expr::Block { statements, tail } => { 235 Expr::Block { statements, tail, .. } => {
229 for stmt in statements { 236 for stmt in statements {
230 match stmt { 237 match stmt {
231 Statement::Let { initializer, .. } => { 238 Statement::Let { initializer, .. } => {
@@ -241,8 +248,8 @@ impl Expr {
241 } 248 }
242 } 249 }
243 Expr::TryBlock { body } => f(*body), 250 Expr::TryBlock { body } => f(*body),
244 Expr::Loop { body } => f(*body), 251 Expr::Loop { body, .. } => f(*body),
245 Expr::While { condition, body } => { 252 Expr::While { condition, body, .. } => {
246 f(*condition); 253 f(*condition);
247 f(*body); 254 f(*body);
248 } 255 }
@@ -268,8 +275,8 @@ impl Expr {
268 f(arm.expr); 275 f(arm.expr);
269 } 276 }
270 } 277 }
271 Expr::Continue => {} 278 Expr::Continue { .. } => {}
272 Expr::Break { expr } | Expr::Return { expr } => { 279 Expr::Break { expr, .. } | Expr::Return { expr } => {
273 if let Some(expr) = expr { 280 if let Some(expr) = expr {
274 f(*expr); 281 f(*expr);
275 } 282 }