diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_analysis/src/call_info.rs | 122 | ||||
-rw-r--r-- | crates/ra_analysis/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/function.rs | 127 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 2 |
4 files changed, 115 insertions, 137 deletions
diff --git a/crates/ra_analysis/src/call_info.rs b/crates/ra_analysis/src/call_info.rs index 2fcd03c9b..911ac3955 100644 --- a/crates/ra_analysis/src/call_info.rs +++ b/crates/ra_analysis/src/call_info.rs | |||
@@ -1,16 +1,17 @@ | |||
1 | use std::cmp::{max, min}; | ||
2 | |||
1 | use ra_db::{SyntaxDatabase, Cancelable}; | 3 | use ra_db::{SyntaxDatabase, Cancelable}; |
2 | use ra_syntax::{ | 4 | use ra_syntax::{ |
3 | AstNode, SyntaxNode, TextUnit, TextRange, | 5 | AstNode, SyntaxNode, TextUnit, TextRange, |
4 | SyntaxKind::FN_DEF, | 6 | SyntaxKind::FN_DEF, |
5 | ast::{self, ArgListOwner}, | 7 | ast::{self, ArgListOwner, DocCommentsOwner}, |
6 | }; | 8 | }; |
7 | use ra_editor::find_node_at_offset; | 9 | use ra_editor::find_node_at_offset; |
8 | use hir::FnSignatureInfo; | ||
9 | 10 | ||
10 | use crate::{FilePosition, CallInfo, db::RootDatabase}; | 11 | use crate::{FilePosition, CallInfo, db::RootDatabase}; |
11 | 12 | ||
12 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Cancelable<Option<CallInfo>> { | 13 | pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Cancelable<Option<CallInfo>> { |
13 | let (sig_info, active_parameter) = ctry!(call_info_(db, position)?); | 14 | let (sig_info, active_parameter) = ctry!(signature_and_active_param(db, position)?); |
14 | let res = CallInfo { | 15 | let res = CallInfo { |
15 | label: sig_info.label, | 16 | label: sig_info.label, |
16 | doc: sig_info.doc, | 17 | doc: sig_info.doc, |
@@ -21,7 +22,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Cancelable | |||
21 | } | 22 | } |
22 | 23 | ||
23 | /// Computes parameter information for the given call expression. | 24 | /// Computes parameter information for the given call expression. |
24 | fn call_info_( | 25 | fn signature_and_active_param( |
25 | db: &RootDatabase, | 26 | db: &RootDatabase, |
26 | position: FilePosition, | 27 | position: FilePosition, |
27 | ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> { | 28 | ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> { |
@@ -39,12 +40,7 @@ fn call_info_( | |||
39 | let fn_file = db.source_file(symbol.file_id); | 40 | let fn_file = db.source_file(symbol.file_id); |
40 | let fn_def = symbol.ptr.resolve(&fn_file); | 41 | let fn_def = symbol.ptr.resolve(&fn_file); |
41 | let fn_def = ast::FnDef::cast(&fn_def).unwrap(); | 42 | let fn_def = ast::FnDef::cast(&fn_def).unwrap(); |
42 | let descr = ctry!(hir::source_binder::function_from_source( | 43 | if let Some(descriptor) = FnSignatureInfo::new(fn_def) { |
43 | db, | ||
44 | symbol.file_id, | ||
45 | fn_def | ||
46 | )?); | ||
47 | if let Some(descriptor) = descr.signature_info(db) { | ||
48 | // If we have a calling expression let's find which argument we are on | 44 | // If we have a calling expression let's find which argument we are on |
49 | let mut current_parameter = None; | 45 | let mut current_parameter = None; |
50 | 46 | ||
@@ -129,6 +125,112 @@ impl<'a> FnCallNode<'a> { | |||
129 | } | 125 | } |
130 | } | 126 | } |
131 | 127 | ||
128 | #[derive(Debug, Clone)] | ||
129 | struct FnSignatureInfo { | ||
130 | label: String, | ||
131 | params: Vec<String>, | ||
132 | doc: Option<String>, | ||
133 | } | ||
134 | |||
135 | impl FnSignatureInfo { | ||
136 | fn new(node: &ast::FnDef) -> Option<Self> { | ||
137 | let mut doc = None; | ||
138 | |||
139 | // Strip the body out for the label. | ||
140 | let mut label: String = if let Some(body) = node.body() { | ||
141 | let body_range = body.syntax().range(); | ||
142 | let label: String = node | ||
143 | .syntax() | ||
144 | .children() | ||
145 | .filter(|child| !child.range().is_subrange(&body_range)) | ||
146 | .map(|node| node.text().to_string()) | ||
147 | .collect(); | ||
148 | label | ||
149 | } else { | ||
150 | node.syntax().text().to_string() | ||
151 | }; | ||
152 | |||
153 | if let Some((comment_range, docs)) = FnSignatureInfo::extract_doc_comments(node) { | ||
154 | let comment_range = comment_range | ||
155 | .checked_sub(node.syntax().range().start()) | ||
156 | .unwrap(); | ||
157 | let start = comment_range.start().to_usize(); | ||
158 | let end = comment_range.end().to_usize(); | ||
159 | |||
160 | // Remove the comment from the label | ||
161 | label.replace_range(start..end, ""); | ||
162 | |||
163 | // Massage markdown | ||
164 | let mut processed_lines = Vec::new(); | ||
165 | let mut in_code_block = false; | ||
166 | for line in docs.lines() { | ||
167 | if line.starts_with("```") { | ||
168 | in_code_block = !in_code_block; | ||
169 | } | ||
170 | |||
171 | let line = if in_code_block && line.starts_with("```") && !line.contains("rust") { | ||
172 | "```rust".into() | ||
173 | } else { | ||
174 | line.to_string() | ||
175 | }; | ||
176 | |||
177 | processed_lines.push(line); | ||
178 | } | ||
179 | |||
180 | if !processed_lines.is_empty() { | ||
181 | doc = Some(processed_lines.join("\n")); | ||
182 | } | ||
183 | } | ||
184 | |||
185 | let params = FnSignatureInfo::param_list(node); | ||
186 | |||
187 | Some(FnSignatureInfo { | ||
188 | params, | ||
189 | label: label.trim().to_owned(), | ||
190 | doc, | ||
191 | }) | ||
192 | } | ||
193 | |||
194 | fn extract_doc_comments(node: &ast::FnDef) -> Option<(TextRange, String)> { | ||
195 | if node.doc_comments().count() == 0 { | ||
196 | return None; | ||
197 | } | ||
198 | |||
199 | let comment_text = node.doc_comment_text(); | ||
200 | |||
201 | let (begin, end) = node | ||
202 | .doc_comments() | ||
203 | .map(|comment| comment.syntax().range()) | ||
204 | .map(|range| (range.start().to_usize(), range.end().to_usize())) | ||
205 | .fold((std::usize::MAX, std::usize::MIN), |acc, range| { | ||
206 | (min(acc.0, range.0), max(acc.1, range.1)) | ||
207 | }); | ||
208 | |||
209 | let range = TextRange::from_to(TextUnit::from_usize(begin), TextUnit::from_usize(end)); | ||
210 | |||
211 | Some((range, comment_text)) | ||
212 | } | ||
213 | |||
214 | fn param_list(node: &ast::FnDef) -> Vec<String> { | ||
215 | let mut res = vec![]; | ||
216 | if let Some(param_list) = node.param_list() { | ||
217 | if let Some(self_param) = param_list.self_param() { | ||
218 | res.push(self_param.syntax().text().to_string()) | ||
219 | } | ||
220 | |||
221 | // Maybe use param.pat here? See if we can just extract the name? | ||
222 | //res.extend(param_list.params().map(|p| p.syntax().text().to_string())); | ||
223 | res.extend( | ||
224 | param_list | ||
225 | .params() | ||
226 | .filter_map(|p| p.pat()) | ||
227 | .map(|pat| pat.syntax().text().to_string()), | ||
228 | ); | ||
229 | } | ||
230 | res | ||
231 | } | ||
232 | } | ||
233 | |||
132 | #[cfg(test)] | 234 | #[cfg(test)] |
133 | mod tests { | 235 | mod tests { |
134 | use super::*; | 236 | use super::*; |
diff --git a/crates/ra_analysis/src/lib.rs b/crates/ra_analysis/src/lib.rs index 4fa6750aa..771a349c8 100644 --- a/crates/ra_analysis/src/lib.rs +++ b/crates/ra_analysis/src/lib.rs | |||
@@ -40,7 +40,6 @@ pub use crate::{ | |||
40 | completion::{CompletionItem, CompletionItemKind, InsertText}, | 40 | completion::{CompletionItem, CompletionItemKind, InsertText}, |
41 | runnables::{Runnable, RunnableKind}, | 41 | runnables::{Runnable, RunnableKind}, |
42 | }; | 42 | }; |
43 | pub use hir::FnSignatureInfo; | ||
44 | pub use ra_editor::{Fold, FoldKind, HighlightedRange, LineIndex, Severity, StructureNode}; | 43 | pub use ra_editor::{Fold, FoldKind, HighlightedRange, LineIndex, Severity, StructureNode}; |
45 | 44 | ||
46 | pub use ra_db::{ | 45 | pub use ra_db::{ |
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 @@ | |||
1 | mod scope; | 1 | mod scope; |
2 | 2 | ||
3 | use std::{ | 3 | use std::sync::Arc; |
4 | cmp::{max, min}, | ||
5 | sync::Arc, | ||
6 | }; | ||
7 | 4 | ||
8 | use ra_db::Cancelable; | 5 | use ra_db::Cancelable; |
9 | use ra_syntax::{ | 6 | use ra_syntax::{ |
10 | TextRange, TextUnit, TreePtr, | 7 | TreePtr, |
11 | ast::{self, AstNode, DocCommentsOwner, NameOwner}, | 8 | ast::{self, AstNode}, |
12 | }; | 9 | }; |
13 | 10 | ||
14 | use crate::{DefId, DefKind, HirDatabase, ty::InferenceResult, Module, Crate, impl_block::ImplBlock, expr::{Body, BodySyntaxMapping}, type_ref::{TypeRef, Mutability}, Name}; | 11 | use 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)] | ||
137 | pub 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 | |||
145 | impl 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 | } | ||
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index f8ac28cf7..197d8c4fd 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -53,8 +53,6 @@ pub use self::{ | |||
53 | impl_block::{ImplBlock, ImplItem}, | 53 | impl_block::{ImplBlock, ImplItem}, |
54 | }; | 54 | }; |
55 | 55 | ||
56 | pub use self::function::FnSignatureInfo; | ||
57 | |||
58 | pub use self::code_model_api::{ | 56 | pub use self::code_model_api::{ |
59 | Crate, CrateDependency, | 57 | Crate, CrateDependency, |
60 | Module, ModuleSource, Problem, | 58 | Module, ModuleSource, Problem, |