diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-09 18:55:44 +0100 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-04-09 18:55:44 +0100 |
commit | 2fc2d4373b2c4e96bebf320a84270eee3afe34aa (patch) | |
tree | 5bdb33ae377b4004f0b28ec5e2edff71b41e8c4e /crates/ra_ide_api/src/display/function_signature.rs | |
parent | 5f700179fc7ed16d2848a6dbc7cf23da3b8df6c7 (diff) | |
parent | 45a2b9252401cc580dfa2e0e761313cc8334d47c (diff) |
Merge #1110
1110: Introduce display module and implement new FunctionSignature for CallInfo's r=matklad a=vipentti
This introduces a new module `display` in `ra_ide_api` that contains UI-related things, in addition this refactors CallInfo's function signatures into a new `FunctionSignature` type, which implements `Display` and can be converted into `lsp_types::SignatureInformation` in the `conv` layer.
Currently only `CallInfo` uses the `FunctionSignature` directly, but `function_label` now uses the same signature and returns it as a string, using the `Display` implementation.
This also fixes #960
I think this similar structure could be applied to other UI-displayable items, so instead of the `ra_ide_api` returning `Strings` we could return some intermediate structures that can be converted into a UI-displayable `String` easily, but that could also provide some additional information.
Co-authored-by: Ville Penttinen <[email protected]>
Diffstat (limited to 'crates/ra_ide_api/src/display/function_signature.rs')
-rw-r--r-- | crates/ra_ide_api/src/display/function_signature.rs | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs new file mode 100644 index 000000000..d09950bce --- /dev/null +++ b/crates/ra_ide_api/src/display/function_signature.rs | |||
@@ -0,0 +1,101 @@ | |||
1 | use super::{where_predicates, generic_parameters}; | ||
2 | use crate::db; | ||
3 | use std::fmt::{self, Display}; | ||
4 | use join_to_string::join; | ||
5 | use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; | ||
6 | use std::convert::From; | ||
7 | use hir::{Docs, Documentation}; | ||
8 | |||
9 | /// Contains information about a function signature | ||
10 | #[derive(Debug)] | ||
11 | pub struct FunctionSignature { | ||
12 | /// Optional visibility | ||
13 | pub visibility: Option<String>, | ||
14 | /// Name of the function | ||
15 | pub name: Option<String>, | ||
16 | /// Documentation for the function | ||
17 | pub doc: Option<Documentation>, | ||
18 | /// Generic parameters | ||
19 | pub generic_parameters: Vec<String>, | ||
20 | /// Parameters of the function | ||
21 | pub parameters: Vec<String>, | ||
22 | /// Optional return type | ||
23 | pub ret_type: Option<String>, | ||
24 | /// Where predicates | ||
25 | pub where_predicates: Vec<String>, | ||
26 | } | ||
27 | |||
28 | impl FunctionSignature { | ||
29 | pub(crate) fn with_doc_opt(mut self, doc: Option<Documentation>) -> Self { | ||
30 | self.doc = doc; | ||
31 | self | ||
32 | } | ||
33 | |||
34 | pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self { | ||
35 | let doc = function.docs(db); | ||
36 | let (_, ast_node) = function.source(db); | ||
37 | FunctionSignature::from(&*ast_node).with_doc_opt(doc) | ||
38 | } | ||
39 | } | ||
40 | |||
41 | impl From<&'_ ast::FnDef> for FunctionSignature { | ||
42 | fn from(node: &ast::FnDef) -> FunctionSignature { | ||
43 | fn param_list(node: &ast::FnDef) -> Vec<String> { | ||
44 | let mut res = vec![]; | ||
45 | if let Some(param_list) = node.param_list() { | ||
46 | if let Some(self_param) = param_list.self_param() { | ||
47 | res.push(self_param.syntax().text().to_string()) | ||
48 | } | ||
49 | |||
50 | res.extend(param_list.params().map(|param| param.syntax().text().to_string())); | ||
51 | } | ||
52 | res | ||
53 | } | ||
54 | |||
55 | FunctionSignature { | ||
56 | visibility: node.visibility().map(|n| n.syntax().text().to_string()), | ||
57 | name: node.name().map(|n| n.text().to_string()), | ||
58 | ret_type: node | ||
59 | .ret_type() | ||
60 | .and_then(|r| r.type_ref()) | ||
61 | .map(|n| n.syntax().text().to_string()), | ||
62 | parameters: param_list(node), | ||
63 | generic_parameters: generic_parameters(node), | ||
64 | where_predicates: where_predicates(node), | ||
65 | // docs are processed separately | ||
66 | doc: None, | ||
67 | } | ||
68 | } | ||
69 | } | ||
70 | |||
71 | impl Display for FunctionSignature { | ||
72 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||
73 | if let Some(t) = &self.visibility { | ||
74 | write!(f, "{} ", t)?; | ||
75 | } | ||
76 | |||
77 | if let Some(name) = &self.name { | ||
78 | write!(f, "fn {}", name)?; | ||
79 | } | ||
80 | |||
81 | if !self.generic_parameters.is_empty() { | ||
82 | join(self.generic_parameters.iter()) | ||
83 | .separator(", ") | ||
84 | .surround_with("<", ">") | ||
85 | .to_fmt(f)?; | ||
86 | } | ||
87 | |||
88 | join(self.parameters.iter()).separator(", ").surround_with("(", ")").to_fmt(f)?; | ||
89 | |||
90 | if let Some(t) = &self.ret_type { | ||
91 | write!(f, " -> {}", t)?; | ||
92 | } | ||
93 | |||
94 | if !self.where_predicates.is_empty() { | ||
95 | write!(f, "\nwhere ")?; | ||
96 | join(self.where_predicates.iter()).separator(",\n ").to_fmt(f)?; | ||
97 | } | ||
98 | |||
99 | Ok(()) | ||
100 | } | ||
101 | } | ||