1 // A signature is a string representation of an item's type signature, excluding
2 // any body. It also includes ids for any defs or refs in the signature. For
10 // The signature string is something like "fn foo(x: String) {}" and the signature
11 // will have defs for `foo` and `x` and a ref for `String`.
13 // All signature text should parse in the correct context (i.e., in a module or
14 // impl, etc.). Clients may want to trim trailing `{}` or `;`. The text of a
15 // signature is not guaranteed to be stable (it may improve or change as the
16 // syntax changes, or whitespace or punctuation may change). It is also likely
17 // not to be pretty - no attempt is made to prettify the text. It is recommended
18 // that clients run the text through Rustfmt.
20 // This module generates Signatures for items by walking the AST and looking up
23 // Signatures do not include visibility info. I'm not sure if this is a feature
24 // or an ommission (FIXME).
26 // FIXME where clauses need implementing, defs/refs in generics are mostly missing.
28 use crate::{id_from_def_id, id_from_node_id, SaveContext}
;
30 use rls_data
::{SigElement, Signature}
;
32 use rustc
::hir
::def
::{Res, DefKind}
;
33 use syntax
::ast
::{self, Extern, NodeId}
;
34 use syntax
::print
::pprust
;
36 pub fn item_signature(item
: &ast
::Item
, scx
: &SaveContext
<'_
, '_
>) -> Option
<Signature
> {
37 if !scx
.config
.signatures
{
40 item
.make(0, None
, scx
).ok()
43 pub fn foreign_item_signature(
44 item
: &ast
::ForeignItem
,
45 scx
: &SaveContext
<'_
, '_
>
46 ) -> Option
<Signature
> {
47 if !scx
.config
.signatures
{
50 item
.make(0, None
, scx
).ok()
53 /// Signature for a struct or tuple field declaration.
54 /// Does not include a trailing comma.
55 pub fn field_signature(field
: &ast
::StructField
, scx
: &SaveContext
<'_
, '_
>) -> Option
<Signature
> {
56 if !scx
.config
.signatures
{
59 field
.make(0, None
, scx
).ok()
62 /// Does not include a trailing comma.
63 pub fn variant_signature(variant
: &ast
::Variant
, scx
: &SaveContext
<'_
, '_
>) -> Option
<Signature
> {
64 if !scx
.config
.signatures
{
67 variant
.make(0, None
, scx
).ok()
70 pub fn method_signature(
73 generics
: &ast
::Generics
,
75 scx
: &SaveContext
<'_
, '_
>,
76 ) -> Option
<Signature
> {
77 if !scx
.config
.signatures
{
80 make_method_signature(id
, ident
, generics
, m
, scx
).ok()
83 pub fn assoc_const_signature(
87 default: Option
<&ast
::Expr
>,
88 scx
: &SaveContext
<'_
, '_
>,
89 ) -> Option
<Signature
> {
90 if !scx
.config
.signatures
{
93 make_assoc_const_signature(id
, ident
, ty
, default, scx
).ok()
96 pub fn assoc_type_signature(
99 bounds
: Option
<&ast
::GenericBounds
>,
100 default: Option
<&ast
::Ty
>,
101 scx
: &SaveContext
<'_
, '_
>,
102 ) -> Option
<Signature
> {
103 if !scx
.config
.signatures
{
106 make_assoc_type_signature(id
, ident
, bounds
, default, scx
).ok()
109 type Result
= std
::result
::Result
<Signature
, &'
static str>;
112 fn make(&self, offset
: usize, id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
;
118 defs
: Vec
<SigElement
>,
119 refs
: Vec
<SigElement
>,
122 sig
.defs
.extend(defs
.into_iter());
123 sig
.refs
.extend(refs
.into_iter());
127 fn replace_text(mut sig
: Signature
, text
: String
) -> Signature
{
132 fn merge_sigs(text
: String
, sigs
: Vec
<Signature
>) -> Signature
{
133 let mut result
= Signature
{
139 let (defs
, refs
): (Vec
<_
>, Vec
<_
>) = sigs
.into_iter().map(|s
| (s
.defs
, s
.refs
)).unzip();
143 .extend(defs
.into_iter().flat_map(|ds
| ds
.into_iter()));
146 .extend(refs
.into_iter().flat_map(|rs
| rs
.into_iter()));
151 fn text_sig(text
: String
) -> Signature
{
159 fn push_extern(text
: &mut String
, ext
: Extern
) {
162 Extern
::Implicit
=> text
.push_str("extern "),
163 Extern
::Explicit(abi
) => text
.push_str(&format
!("extern \"{}\" ", abi
.symbol
)),
167 impl Sig
for ast
::Ty
{
168 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
169 let id
= Some(self.id
);
171 ast
::TyKind
::Slice(ref ty
) => {
172 let nested
= ty
.make(offset
+ 1, id
, scx
)?
;
173 let text
= format
!("[{}]", nested
.text
);
174 Ok(replace_text(nested
, text
))
176 ast
::TyKind
::Ptr(ref mt
) => {
177 let prefix
= match mt
.mutbl
{
178 ast
::Mutability
::Mutable
=> "*mut ",
179 ast
::Mutability
::Immutable
=> "*const ",
181 let nested
= mt
.ty
.make(offset
+ prefix
.len(), id
, scx
)?
;
182 let text
= format
!("{}{}", prefix
, nested
.text
);
183 Ok(replace_text(nested
, text
))
185 ast
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
186 let mut prefix
= "&".to_owned();
187 if let &Some(ref l
) = lifetime
{
188 prefix
.push_str(&l
.ident
.to_string());
191 if let ast
::Mutability
::Mutable
= mt
.mutbl
{
192 prefix
.push_str("mut ");
195 let nested
= mt
.ty
.make(offset
+ prefix
.len(), id
, scx
)?
;
196 let text
= format
!("{}{}", prefix
, nested
.text
);
197 Ok(replace_text(nested
, text
))
199 ast
::TyKind
::Never
=> Ok(text_sig("!".to_owned())),
200 ast
::TyKind
::CVarArgs
=> Ok(text_sig("...".to_owned())),
201 ast
::TyKind
::Tup(ref ts
) => {
202 let mut text
= "(".to_owned();
203 let mut defs
= vec
![];
204 let mut refs
= vec
![];
206 let nested
= t
.make(offset
+ text
.len(), id
, scx
)?
;
207 text
.push_str(&nested
.text
);
209 defs
.extend(nested
.defs
.into_iter());
210 refs
.extend(nested
.refs
.into_iter());
213 Ok(Signature { text, defs, refs }
)
215 ast
::TyKind
::Paren(ref ty
) => {
216 let nested
= ty
.make(offset
+ 1, id
, scx
)?
;
217 let text
= format
!("({})", nested
.text
);
218 Ok(replace_text(nested
, text
))
220 ast
::TyKind
::BareFn(ref f
) => {
221 let mut text
= String
::new();
222 if !f
.generic_params
.is_empty() {
223 // FIXME defs, bounds on lifetimes
224 text
.push_str("for<");
225 text
.push_str(&f
.generic_params
227 .filter_map(|param
| match param
.kind
{
228 ast
::GenericParamKind
::Lifetime { .. }
=> {
229 Some(param
.ident
.to_string())
238 if f
.unsafety
== ast
::Unsafety
::Unsafe
{
239 text
.push_str("unsafe ");
241 push_extern(&mut text
, f
.ext
);
242 text
.push_str("fn(");
244 let mut defs
= vec
![];
245 let mut refs
= vec
![];
246 for i
in &f
.decl
.inputs
{
247 let nested
= i
.ty
.make(offset
+ text
.len(), Some(i
.id
), scx
)?
;
248 text
.push_str(&nested
.text
);
250 defs
.extend(nested
.defs
.into_iter());
251 refs
.extend(nested
.refs
.into_iter());
254 if let ast
::FunctionRetTy
::Ty(ref t
) = f
.decl
.output
{
255 text
.push_str(" -> ");
256 let nested
= t
.make(offset
+ text
.len(), None
, scx
)?
;
257 text
.push_str(&nested
.text
);
259 defs
.extend(nested
.defs
.into_iter());
260 refs
.extend(nested
.refs
.into_iter());
263 Ok(Signature { text, defs, refs }
)
265 ast
::TyKind
::Path(None
, ref path
) => path
.make(offset
, id
, scx
),
266 ast
::TyKind
::Path(Some(ref qself
), ref path
) => {
267 let nested_ty
= qself
.ty
.make(offset
+ 1, id
, scx
)?
;
268 let prefix
= if qself
.position
== 0 {
269 format
!("<{}>::", nested_ty
.text
)
270 } else if qself
.position
== 1 {
271 let first
= pprust
::path_segment_to_string(&path
.segments
[0]);
272 format
!("<{} as {}>::", nested_ty
.text
, first
)
274 // FIXME handle path instead of elipses.
275 format
!("<{} as ...>::", nested_ty
.text
)
278 let name
= pprust
::path_segment_to_string(path
.segments
.last().ok_or("Bad path")?
);
279 let res
= scx
.get_path_res(id
.ok_or("Missing id for Path")?
);
280 let id
= id_from_def_id(res
.def_id());
281 if path
.segments
.len() - qself
.position
== 1 {
282 let start
= offset
+ prefix
.len();
283 let end
= start
+ name
.len();
286 text
: prefix
+ &name
,
288 refs
: vec
![SigElement { id, start, end }
],
291 let start
= offset
+ prefix
.len() + 5;
292 let end
= start
+ name
.len();
293 // FIXME should put the proper path in there, not elipses.
295 text
: prefix
+ "...::" + &name
,
297 refs
: vec
![SigElement { id, start, end }
],
301 ast
::TyKind
::TraitObject(ref bounds
, ..) => {
302 // FIXME recurse into bounds
303 let nested
= pprust
::bounds_to_string(bounds
);
306 ast
::TyKind
::ImplTrait(_
, ref bounds
) => {
307 // FIXME recurse into bounds
308 let nested
= pprust
::bounds_to_string(bounds
);
309 Ok(text_sig(format
!("impl {}", nested
)))
311 ast
::TyKind
::Array(ref ty
, ref v
) => {
312 let nested_ty
= ty
.make(offset
+ 1, id
, scx
)?
;
313 let expr
= pprust
::expr_to_string(&v
.value
).replace('
\n'
, " ");
314 let text
= format
!("[{}; {}]", nested_ty
.text
, expr
);
315 Ok(replace_text(nested_ty
, text
))
317 ast
::TyKind
::Typeof(_
) |
320 ast
::TyKind
::ImplicitSelf
|
321 ast
::TyKind
::Mac(_
) => Err("Ty"),
326 impl Sig
for ast
::Item
{
327 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
328 let id
= Some(self.id
);
331 ast
::ItemKind
::Static(ref ty
, m
, ref expr
) => {
332 let mut text
= "static ".to_owned();
333 if m
== ast
::Mutability
::Mutable
{
334 text
.push_str("mut ");
336 let name
= self.ident
.to_string();
339 id
: id_from_node_id(self.id
, scx
),
340 start
: offset
+ text
.len(),
341 end
: offset
+ text
.len() + name
.len(),
344 text
.push_str(&name
);
347 let ty
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
348 text
.push_str(&ty
.text
);
349 text
.push_str(" = ");
351 let expr
= pprust
::expr_to_string(expr
).replace('
\n'
, " ");
352 text
.push_str(&expr
);
355 Ok(extend_sig(ty
, text
, defs
, vec
![]))
357 ast
::ItemKind
::Const(ref ty
, ref expr
) => {
358 let mut text
= "const ".to_owned();
359 let name
= self.ident
.to_string();
362 id
: id_from_node_id(self.id
, scx
),
363 start
: offset
+ text
.len(),
364 end
: offset
+ text
.len() + name
.len(),
367 text
.push_str(&name
);
370 let ty
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
371 text
.push_str(&ty
.text
);
372 text
.push_str(" = ");
374 let expr
= pprust
::expr_to_string(expr
).replace('
\n'
, " ");
375 text
.push_str(&expr
);
378 Ok(extend_sig(ty
, text
, defs
, vec
![]))
380 ast
::ItemKind
::Fn(ast
::FnSig { ref decl, header }
, ref generics
, _
) => {
381 let mut text
= String
::new();
382 if header
.constness
.node
== ast
::Constness
::Const
{
383 text
.push_str("const ");
385 if header
.asyncness
.node
.is_async() {
386 text
.push_str("async ");
388 if header
.unsafety
== ast
::Unsafety
::Unsafe
{
389 text
.push_str("unsafe ");
391 push_extern(&mut text
, header
.ext
);
392 text
.push_str("fn ");
394 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
397 for i
in &decl
.inputs
{
398 // FIXME should descend into patterns to add defs.
399 sig
.text
.push_str(&pprust
::pat_to_string(&i
.pat
));
400 sig
.text
.push_str(": ");
401 let nested
= i
.ty
.make(offset
+ sig
.text
.len(), Some(i
.id
), scx
)?
;
402 sig
.text
.push_str(&nested
.text
);
404 sig
.defs
.extend(nested
.defs
.into_iter());
405 sig
.refs
.extend(nested
.refs
.into_iter());
409 if let ast
::FunctionRetTy
::Ty(ref t
) = decl
.output
{
410 sig
.text
.push_str(" -> ");
411 let nested
= t
.make(offset
+ sig
.text
.len(), None
, scx
)?
;
412 sig
.text
.push_str(&nested
.text
);
413 sig
.defs
.extend(nested
.defs
.into_iter());
414 sig
.refs
.extend(nested
.refs
.into_iter());
416 sig
.text
.push_str(" {}");
420 ast
::ItemKind
::Mod(ref _mod
) => {
421 let mut text
= "mod ".to_owned();
422 let name
= self.ident
.to_string();
425 id
: id_from_node_id(self.id
, scx
),
426 start
: offset
+ text
.len(),
427 end
: offset
+ text
.len() + name
.len(),
430 text
.push_str(&name
);
431 // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
440 ast
::ItemKind
::TyAlias(ref ty
, ref generics
) => {
441 let text
= "type ".to_owned();
442 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
444 sig
.text
.push_str(" = ");
445 let ty
= ty
.make(offset
+ sig
.text
.len(), id
, scx
)?
;
446 sig
.text
.push_str(&ty
.text
);
449 Ok(merge_sigs(sig
.text
.clone(), vec
![sig
, ty
]))
451 ast
::ItemKind
::Enum(_
, ref generics
) => {
452 let text
= "enum ".to_owned();
453 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
454 sig
.text
.push_str(" {}");
457 ast
::ItemKind
::Struct(_
, ref generics
) => {
458 let text
= "struct ".to_owned();
459 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
460 sig
.text
.push_str(" {}");
463 ast
::ItemKind
::Union(_
, ref generics
) => {
464 let text
= "union ".to_owned();
465 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
466 sig
.text
.push_str(" {}");
469 ast
::ItemKind
::Trait(is_auto
, unsafety
, ref generics
, ref bounds
, _
) => {
470 let mut text
= String
::new();
472 if is_auto
== ast
::IsAuto
::Yes
{
473 text
.push_str("auto ");
476 if unsafety
== ast
::Unsafety
::Unsafe
{
477 text
.push_str("unsafe ");
479 text
.push_str("trait ");
480 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
482 if !bounds
.is_empty() {
483 sig
.text
.push_str(": ");
484 sig
.text
.push_str(&pprust
::bounds_to_string(bounds
));
486 // FIXME where clause
487 sig
.text
.push_str(" {}");
491 ast
::ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
492 let mut text
= String
::new();
493 text
.push_str("trait ");
494 let mut sig
= name_and_generics(text
,
501 if !bounds
.is_empty() {
502 sig
.text
.push_str(" = ");
503 sig
.text
.push_str(&pprust
::bounds_to_string(bounds
));
505 // FIXME where clause
506 sig
.text
.push_str(";");
519 let mut text
= String
::new();
520 if let ast
::Defaultness
::Default
= defaultness
{
521 text
.push_str("default ");
523 if unsafety
== ast
::Unsafety
::Unsafe
{
524 text
.push_str("unsafe ");
526 text
.push_str("impl");
528 let generics_sig
= generics
.make(offset
+ text
.len(), id
, scx
)?
;
529 text
.push_str(&generics_sig
.text
);
533 let trait_sig
= if let Some(ref t
) = *opt_trait
{
534 if polarity
== ast
::ImplPolarity
::Negative
{
537 let trait_sig
= t
.path
.make(offset
+ text
.len(), id
, scx
)?
;
538 text
.push_str(&trait_sig
.text
);
539 text
.push_str(" for ");
542 text_sig(String
::new())
545 let ty_sig
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
546 text
.push_str(&ty_sig
.text
);
548 text
.push_str(" {}");
550 Ok(merge_sigs(text
, vec
![generics_sig
, trait_sig
, ty_sig
]))
552 // FIXME where clause
554 ast
::ItemKind
::ForeignMod(_
) => Err("extern mod"),
555 ast
::ItemKind
::GlobalAsm(_
) => Err("glboal asm"),
556 ast
::ItemKind
::ExternCrate(_
) => Err("extern crate"),
557 // FIXME should implement this (e.g., pub use).
558 ast
::ItemKind
::Use(_
) => Err("import"),
559 ast
::ItemKind
::Mac(..) | ast
::ItemKind
::MacroDef(_
) => Err("Macro"),
564 impl Sig
for ast
::Path
{
565 fn make(&self, offset
: usize, id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
566 let res
= scx
.get_path_res(id
.ok_or("Missing id for Path")?
);
568 let (name
, start
, end
) = match res
{
569 Res
::PrimTy(..) | Res
::SelfTy(..) | Res
::Err
=> {
570 return Ok(Signature
{
571 text
: pprust
::path_to_string(self),
576 Res
::Def(DefKind
::AssocConst
, _
)
577 | Res
::Def(DefKind
::Variant
, _
)
578 | Res
::Def(DefKind
::Ctor(..), _
) => {
579 let len
= self.segments
.len();
581 return Err("Bad path");
583 // FIXME: really we should descend into the generics here and add SigElements for
585 // FIXME: would be nice to have a def for the first path segment.
586 let seg1
= pprust
::path_segment_to_string(&self.segments
[len
- 2]);
587 let seg2
= pprust
::path_segment_to_string(&self.segments
[len
- 1]);
588 let start
= offset
+ seg1
.len() + 2;
589 (format
!("{}::{}", seg1
, seg2
), start
, start
+ seg2
.len())
592 let name
= pprust
::path_segment_to_string(self.segments
.last().ok_or("Bad path")?
);
593 let end
= offset
+ name
.len();
598 let id
= id_from_def_id(res
.def_id());
602 refs
: vec
![SigElement { id, start, end }
],
607 // This does not cover the where clause, which must be processed separately.
608 impl Sig
for ast
::Generics
{
609 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
610 if self.params
.is_empty() {
611 return Ok(text_sig(String
::new()));
614 let mut text
= "<".to_owned();
616 let mut defs
= Vec
::with_capacity(self.params
.len());
617 for param
in &self.params
{
618 let mut param_text
= String
::new();
619 if let ast
::GenericParamKind
::Const { .. }
= param
.kind
{
620 param_text
.push_str("const ");
622 param_text
.push_str(¶m
.ident
.as_str());
623 defs
.push(SigElement
{
624 id
: id_from_node_id(param
.id
, scx
),
625 start
: offset
+ text
.len(),
626 end
: offset
+ text
.len() + param_text
.as_str().len(),
628 if let ast
::GenericParamKind
::Const { ref ty }
= param
.kind
{
629 param_text
.push_str(": ");
630 param_text
.push_str(&pprust
::ty_to_string(&ty
));
632 if !param
.bounds
.is_empty() {
633 param_text
.push_str(": ");
635 ast
::GenericParamKind
::Lifetime { .. }
=> {
636 let bounds
= param
.bounds
.iter()
637 .map(|bound
| match bound
{
638 ast
::GenericBound
::Outlives(lt
) => lt
.ident
.to_string(),
643 param_text
.push_str(&bounds
);
644 // FIXME add lifetime bounds refs.
646 ast
::GenericParamKind
::Type { .. }
=> {
647 param_text
.push_str(&pprust
::bounds_to_string(¶m
.bounds
));
648 // FIXME descend properly into bounds.
650 ast
::GenericParamKind
::Const { .. }
=> {
651 // Const generics cannot contain bounds.
655 text
.push_str(¶m_text
);
668 impl Sig
for ast
::StructField
{
669 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
670 let mut text
= String
::new();
672 if let Some(ident
) = self.ident
{
673 text
.push_str(&ident
.to_string());
674 defs
= Some(SigElement
{
675 id
: id_from_node_id(self.id
, scx
),
677 end
: offset
+ text
.len(),
682 let mut ty_sig
= self.ty
.make(offset
+ text
.len(), Some(self.id
), scx
)?
;
683 text
.push_str(&ty_sig
.text
);
685 ty_sig
.defs
.extend(defs
.into_iter());
691 impl Sig
for ast
::Variant
{
692 fn make(&self, offset
: usize, parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
693 let mut text
= self.ident
.to_string();
695 ast
::VariantData
::Struct(ref fields
, r
) => {
696 let id
= parent_id
.unwrap();
697 let name_def
= SigElement
{
698 id
: id_from_node_id(id
, scx
),
700 end
: offset
+ text
.len(),
702 text
.push_str(" { ");
703 let mut defs
= vec
![name_def
];
704 let mut refs
= vec
![];
706 text
.push_str("/* parse error */ ");
709 let field_sig
= f
.make(offset
+ text
.len(), Some(id
), scx
)?
;
710 text
.push_str(&field_sig
.text
);
712 defs
.extend(field_sig
.defs
.into_iter());
713 refs
.extend(field_sig
.refs
.into_iter());
717 Ok(Signature { text, defs, refs }
)
719 ast
::VariantData
::Tuple(ref fields
, id
) => {
720 let name_def
= SigElement
{
721 id
: id_from_node_id(id
, scx
),
723 end
: offset
+ text
.len(),
726 let mut defs
= vec
![name_def
];
727 let mut refs
= vec
![];
729 let field_sig
= f
.make(offset
+ text
.len(), Some(id
), scx
)?
;
730 text
.push_str(&field_sig
.text
);
732 defs
.extend(field_sig
.defs
.into_iter());
733 refs
.extend(field_sig
.refs
.into_iter());
736 Ok(Signature { text, defs, refs }
)
738 ast
::VariantData
::Unit(id
) => {
739 let name_def
= SigElement
{
740 id
: id_from_node_id(id
, scx
),
742 end
: offset
+ text
.len(),
746 defs
: vec
![name_def
],
754 impl Sig
for ast
::ForeignItem
{
755 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
756 let id
= Some(self.id
);
758 ast
::ForeignItemKind
::Fn(ref decl
, ref generics
) => {
759 let mut text
= String
::new();
760 text
.push_str("fn ");
762 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
765 for i
in &decl
.inputs
{
766 // FIXME should descend into patterns to add defs.
767 sig
.text
.push_str(&pprust
::pat_to_string(&i
.pat
));
768 sig
.text
.push_str(": ");
769 let nested
= i
.ty
.make(offset
+ sig
.text
.len(), Some(i
.id
), scx
)?
;
770 sig
.text
.push_str(&nested
.text
);
772 sig
.defs
.extend(nested
.defs
.into_iter());
773 sig
.refs
.extend(nested
.refs
.into_iter());
777 if let ast
::FunctionRetTy
::Ty(ref t
) = decl
.output
{
778 sig
.text
.push_str(" -> ");
779 let nested
= t
.make(offset
+ sig
.text
.len(), None
, scx
)?
;
780 sig
.text
.push_str(&nested
.text
);
781 sig
.defs
.extend(nested
.defs
.into_iter());
782 sig
.refs
.extend(nested
.refs
.into_iter());
788 ast
::ForeignItemKind
::Static(ref ty
, m
) => {
789 let mut text
= "static ".to_owned();
790 if m
== ast
::Mutability
::Mutable
{
791 text
.push_str("mut ");
793 let name
= self.ident
.to_string();
796 id
: id_from_node_id(self.id
, scx
),
797 start
: offset
+ text
.len(),
798 end
: offset
+ text
.len() + name
.len(),
801 text
.push_str(&name
);
804 let ty_sig
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
807 Ok(extend_sig(ty_sig
, text
, defs
, vec
![]))
809 ast
::ForeignItemKind
::Ty
=> {
810 let mut text
= "type ".to_owned();
811 let name
= self.ident
.to_string();
814 id
: id_from_node_id(self.id
, scx
),
815 start
: offset
+ text
.len(),
816 end
: offset
+ text
.len() + name
.len(),
819 text
.push_str(&name
);
828 ast
::ForeignItemKind
::Macro(..) => Err("macro"),
833 fn name_and_generics(
836 generics
: &ast
::Generics
,
839 scx
: &SaveContext
<'_
, '_
>,
841 let name
= name
.to_string();
842 let def
= SigElement
{
843 id
: id_from_node_id(id
, scx
),
844 start
: offset
+ text
.len(),
845 end
: offset
+ text
.len() + name
.len(),
847 text
.push_str(&name
);
848 let generics
: Signature
= generics
.make(offset
+ text
.len(), Some(id
), scx
)?
;
849 // FIXME where clause
850 let text
= format
!("{}{}", text
, generics
.text
);
851 Ok(extend_sig(generics
, text
, vec
![def
], vec
![]))
855 fn make_assoc_type_signature(
858 bounds
: Option
<&ast
::GenericBounds
>,
859 default: Option
<&ast
::Ty
>,
860 scx
: &SaveContext
<'_
, '_
>,
862 let mut text
= "type ".to_owned();
863 let name
= ident
.to_string();
866 id
: id_from_node_id(id
, scx
),
868 end
: text
.len() + name
.len(),
871 let mut refs
= vec
![];
872 text
.push_str(&name
);
873 if let Some(bounds
) = bounds
{
875 // FIXME should descend into bounds
876 text
.push_str(&pprust
::bounds_to_string(bounds
));
878 if let Some(default) = default {
879 text
.push_str(" = ");
880 let ty_sig
= default.make(text
.len(), Some(id
), scx
)?
;
881 text
.push_str(&ty_sig
.text
);
882 defs
.extend(ty_sig
.defs
.into_iter());
883 refs
.extend(ty_sig
.refs
.into_iter());
886 Ok(Signature { text, defs, refs }
)
889 fn make_assoc_const_signature(
893 default: Option
<&ast
::Expr
>,
894 scx
: &SaveContext
<'_
, '_
>,
896 let mut text
= "const ".to_owned();
897 let name
= ident
.to_string();
900 id
: id_from_node_id(id
, scx
),
902 end
: text
.len() + name
.len(),
905 let mut refs
= vec
![];
906 text
.push_str(&name
);
909 let ty_sig
= ty
.make(text
.len(), Some(id
), scx
)?
;
910 text
.push_str(&ty_sig
.text
);
911 defs
.extend(ty_sig
.defs
.into_iter());
912 refs
.extend(ty_sig
.refs
.into_iter());
914 if let Some(default) = default {
915 text
.push_str(" = ");
916 text
.push_str(&pprust
::expr_to_string(default));
919 Ok(Signature { text, defs, refs }
)
922 fn make_method_signature(
925 generics
: &ast
::Generics
,
927 scx
: &SaveContext
<'_
, '_
>,
929 // FIXME code dup with function signature
930 let mut text
= String
::new();
931 if m
.header
.constness
.node
== ast
::Constness
::Const
{
932 text
.push_str("const ");
934 if m
.header
.asyncness
.node
.is_async() {
935 text
.push_str("async ");
937 if m
.header
.unsafety
== ast
::Unsafety
::Unsafe
{
938 text
.push_str("unsafe ");
940 push_extern(&mut text
, m
.header
.ext
);
941 text
.push_str("fn ");
943 let mut sig
= name_and_generics(text
, 0, generics
, id
, ident
, scx
)?
;
946 for i
in &m
.decl
.inputs
{
947 // FIXME should descend into patterns to add defs.
948 sig
.text
.push_str(&pprust
::pat_to_string(&i
.pat
));
949 sig
.text
.push_str(": ");
950 let nested
= i
.ty
.make(sig
.text
.len(), Some(i
.id
), scx
)?
;
951 sig
.text
.push_str(&nested
.text
);
953 sig
.defs
.extend(nested
.defs
.into_iter());
954 sig
.refs
.extend(nested
.refs
.into_iter());
958 if let ast
::FunctionRetTy
::Ty(ref t
) = m
.decl
.output
{
959 sig
.text
.push_str(" -> ");
960 let nested
= t
.make(sig
.text
.len(), None
, scx
)?
;
961 sig
.text
.push_str(&nested
.text
);
962 sig
.defs
.extend(nested
.defs
.into_iter());
963 sig
.refs
.extend(nested
.refs
.into_iter());
965 sig
.text
.push_str(" {}");