aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/function.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/function.rs')
-rw-r--r--crates/ra_hir/src/function.rs127
1 files changed, 3 insertions, 124 deletions
diff --git a/crates/ra_hir/src/function.rs b/crates/ra_hir/src/function.rs
index 81b790c5f..2cfc4caa4 100644
--- a/crates/ra_hir/src/function.rs
+++ b/crates/ra_hir/src/function.rs
@@ -1,14 +1,11 @@
1mod scope; 1mod scope;
2 2
3use std::{ 3use std::sync::Arc;
4 cmp::{max, min},
5 sync::Arc,
6};
7 4
8use ra_db::Cancelable; 5use ra_db::Cancelable;
9use ra_syntax::{ 6use ra_syntax::{
10 TextRange, TextUnit, TreePtr, 7 TreePtr,
11 ast::{self, AstNode, DocCommentsOwner, NameOwner}, 8 ast::{self, AstNode},
12}; 9};
13 10
14use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock, expr::{Body, BodySyntaxMapping}, type_ref::{TypeRef, Mutability}, Name}; 11use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock, expr::{Body, BodySyntaxMapping}, type_ref::{TypeRef, Mutability}, Name};
@@ -57,11 +54,6 @@ impl Function {
57 db.fn_signature(self.def_id) 54 db.fn_signature(self.def_id)
58 } 55 }
59 56
60 pub fn signature_info(&self, db: &impl HirDatabase) -> Option<FnSignatureInfo> {
61 let syntax = self.syntax(db);
62 FnSignatureInfo::new(&syntax)
63 }
64
65 pub fn infer(&self, db: &impl HirDatabase) -> Cancelable<Arc<InferenceResult>> { 57 pub fn infer(&self, db: &impl HirDatabase) -> Cancelable<Arc<InferenceResult>> {
66 db.infer(self.def_id) 58 db.infer(self.def_id)
67 } 59 }
@@ -132,116 +124,3 @@ pub(crate) fn fn_signature(db: &impl HirDatabase, def_id: DefId) -> Arc<FnSignat
132 let sig = FnSignature { args, ret_type }; 124 let sig = FnSignature { args, ret_type };
133 Arc::new(sig) 125 Arc::new(sig)
134} 126}
135
136#[derive(Debug, Clone)]
137pub struct FnSignatureInfo {
138 pub name: String,
139 pub label: String,
140 pub ret_type: Option<String>,
141 pub params: Vec<String>,
142 pub doc: Option<String>,
143}
144
145impl FnSignatureInfo {
146 fn new(node: &ast::FnDef) -> Option<Self> {
147 let name = node.name()?.text().to_string();
148
149 let mut doc = None;
150
151 // Strip the body out for the label.
152 let mut label: String = if let Some(body) = node.body() {
153 let body_range = body.syntax().range();
154 let label: String = node
155 .syntax()
156 .children()
157 .filter(|child| !child.range().is_subrange(&body_range))
158 .map(|node| node.text().to_string())
159 .collect();
160 label
161 } else {
162 node.syntax().text().to_string()
163 };
164
165 if let Some((comment_range, docs)) = FnSignatureInfo::extract_doc_comments(node) {
166 let comment_range = comment_range
167 .checked_sub(node.syntax().range().start())
168 .unwrap();
169 let start = comment_range.start().to_usize();
170 let end = comment_range.end().to_usize();
171
172 // Remove the comment from the label
173 label.replace_range(start..end, "");
174
175 // Massage markdown
176 let mut processed_lines = Vec::new();
177 let mut in_code_block = false;
178 for line in docs.lines() {
179 if line.starts_with("```") {
180 in_code_block = !in_code_block;
181 }
182
183 let line = if in_code_block && line.starts_with("```") && !line.contains("rust") {
184 "```rust".into()
185 } else {
186 line.to_string()
187 };
188
189 processed_lines.push(line);
190 }
191
192 if !processed_lines.is_empty() {
193 doc = Some(processed_lines.join("\n"));
194 }
195 }
196
197 let params = FnSignatureInfo::param_list(node);
198 let ret_type = node.ret_type().map(|r| r.syntax().text().to_string());
199
200 Some(FnSignatureInfo {
201 name,
202 ret_type,
203 params,
204 label: label.trim().to_owned(),
205 doc,
206 })
207 }
208
209 fn extract_doc_comments(node: &ast::FnDef) -> Option<(TextRange, String)> {
210 if node.doc_comments().count() == 0 {
211 return None;
212 }
213
214 let comment_text = node.doc_comment_text();
215
216 let (begin, end) = node
217 .doc_comments()
218 .map(|comment| comment.syntax().range())
219 .map(|range| (range.start().to_usize(), range.end().to_usize()))
220 .fold((std::usize::MAX, std::usize::MIN), |acc, range| {
221 (min(acc.0, range.0), max(acc.1, range.1))
222 });
223
224 let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end));
225
226 Some((range, comment_text))
227 }
228
229 fn param_list(node: &ast::FnDef) -> Vec<String> {
230 let mut res = vec![];
231 if let Some(param_list) = node.param_list() {
232 if let Some(self_param) = param_list.self_param() {
233 res.push(self_param.syntax().text().to_string())
234 }
235
236 // Maybe use param.pat here? See if we can just extract the name?
237 //res.extend(param_list.params().map(|p| p.syntax().text().to_string()));
238 res.extend(
239 param_list
240 .params()
241 .filter_map(|p| p.pat())
242 .map(|pat| pat.syntax().text().to_string()),
243 );
244 }
245 res
246 }
247}