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 omission (FIXME).
26 // FIXME where clauses need implementing, defs/refs in generics are mostly missing.
28 use crate::{id_from_def_id, id_from_hir_id, SaveContext}
;
30 use rls_data
::{SigElement, Signature}
;
32 use rustc_ast
::Mutability
;
34 use rustc_hir
::def
::{DefKind, Res}
;
35 use rustc_hir_pretty
::id_to_string
;
36 use rustc_hir_pretty
::{bounds_to_string, path_segment_to_string, path_to_string, ty_to_string}
;
37 use rustc_span
::symbol
::{Ident, Symbol}
;
39 pub fn item_signature(item
: &hir
::Item
<'_
>, scx
: &SaveContext
<'_
>) -> Option
<Signature
> {
40 if !scx
.config
.signatures
{
43 item
.make(0, None
, scx
).ok()
46 pub fn foreign_item_signature(
47 item
: &hir
::ForeignItem
<'_
>,
48 scx
: &SaveContext
<'_
>,
49 ) -> Option
<Signature
> {
50 if !scx
.config
.signatures
{
53 item
.make(0, None
, scx
).ok()
56 /// Signature for a struct or tuple field declaration.
57 /// Does not include a trailing comma.
58 pub fn field_signature(field
: &hir
::FieldDef
<'_
>, scx
: &SaveContext
<'_
>) -> Option
<Signature
> {
59 if !scx
.config
.signatures
{
62 field
.make(0, None
, scx
).ok()
65 /// Does not include a trailing comma.
66 pub fn variant_signature(variant
: &hir
::Variant
<'_
>, scx
: &SaveContext
<'_
>) -> Option
<Signature
> {
67 if !scx
.config
.signatures
{
70 variant
.make(0, None
, scx
).ok()
73 pub fn method_signature(
76 generics
: &hir
::Generics
<'_
>,
78 scx
: &SaveContext
<'_
>,
79 ) -> Option
<Signature
> {
80 if !scx
.config
.signatures
{
83 make_method_signature(id
, ident
, generics
, m
, scx
).ok()
86 pub fn assoc_const_signature(
90 default: Option
<&hir
::Expr
<'_
>>,
91 scx
: &SaveContext
<'_
>,
92 ) -> Option
<Signature
> {
93 if !scx
.config
.signatures
{
96 make_assoc_const_signature(id
, ident
, ty
, default, scx
).ok()
99 pub fn assoc_type_signature(
102 bounds
: Option
<hir
::GenericBounds
<'_
>>,
103 default: Option
<&hir
::Ty
<'_
>>,
104 scx
: &SaveContext
<'_
>,
105 ) -> Option
<Signature
> {
106 if !scx
.config
.signatures
{
109 make_assoc_type_signature(id
, ident
, bounds
, default, scx
).ok()
112 type Result
= std
::result
::Result
<Signature
, &'
static str>;
115 fn make(&self, offset
: usize, id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
;
121 defs
: Vec
<SigElement
>,
122 refs
: Vec
<SigElement
>,
125 sig
.defs
.extend(defs
.into_iter());
126 sig
.refs
.extend(refs
.into_iter());
130 fn replace_text(mut sig
: Signature
, text
: String
) -> Signature
{
135 fn merge_sigs(text
: String
, sigs
: Vec
<Signature
>) -> Signature
{
136 let mut result
= Signature { text, defs: vec![], refs: vec![] }
;
138 let (defs
, refs
): (Vec
<_
>, Vec
<_
>) = sigs
.into_iter().map(|s
| (s
.defs
, s
.refs
)).unzip();
140 result
.defs
.extend(defs
.into_iter().flat_map(|ds
| ds
.into_iter()));
141 result
.refs
.extend(refs
.into_iter().flat_map(|rs
| rs
.into_iter()));
146 fn text_sig(text
: String
) -> Signature
{
147 Signature { text, defs: vec![], refs: vec![] }
150 impl<'hir
> Sig
for hir
::Ty
<'hir
> {
151 fn make(&self, offset
: usize, _parent_id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
{
152 let id
= Some(self.hir_id
);
154 hir
::TyKind
::Slice(ref ty
) => {
155 let nested
= ty
.make(offset
+ 1, id
, scx
)?
;
156 let text
= format
!("[{}]", nested
.text
);
157 Ok(replace_text(nested
, text
))
159 hir
::TyKind
::Ptr(ref mt
) => {
160 let prefix
= match mt
.mutbl
{
161 hir
::Mutability
::Mut
=> "*mut ",
162 hir
::Mutability
::Not
=> "*const ",
164 let nested
= mt
.ty
.make(offset
+ prefix
.len(), id
, scx
)?
;
165 let text
= format
!("{}{}", prefix
, nested
.text
);
166 Ok(replace_text(nested
, text
))
168 hir
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
169 let mut prefix
= "&".to_owned();
170 prefix
.push_str(&lifetime
.ident
.to_string());
172 if mt
.mutbl
.is_mut() {
173 prefix
.push_str("mut ");
176 let nested
= mt
.ty
.make(offset
+ prefix
.len(), id
, scx
)?
;
177 let text
= format
!("{}{}", prefix
, nested
.text
);
178 Ok(replace_text(nested
, text
))
180 hir
::TyKind
::Never
=> Ok(text_sig("!".to_owned())),
181 hir
::TyKind
::Tup(ts
) => {
182 let mut text
= "(".to_owned();
183 let mut defs
= vec
![];
184 let mut refs
= vec
![];
186 let nested
= t
.make(offset
+ text
.len(), id
, scx
)?
;
187 text
.push_str(&nested
.text
);
189 defs
.extend(nested
.defs
.into_iter());
190 refs
.extend(nested
.refs
.into_iter());
193 Ok(Signature { text, defs, refs }
)
195 hir
::TyKind
::BareFn(ref f
) => {
196 let mut text
= String
::new();
197 if !f
.generic_params
.is_empty() {
198 // FIXME defs, bounds on lifetimes
199 text
.push_str("for<");
203 .filter_map(|param
| match param
.kind
{
204 hir
::GenericParamKind
::Lifetime { .. }
=> {
205 Some(param
.name
.ident().to_string())
215 if let hir
::Unsafety
::Unsafe
= f
.unsafety
{
216 text
.push_str("unsafe ");
218 text
.push_str("fn(");
220 let mut defs
= vec
![];
221 let mut refs
= vec
![];
222 for i
in f
.decl
.inputs
{
223 let nested
= i
.make(offset
+ text
.len(), Some(i
.hir_id
), scx
)?
;
224 text
.push_str(&nested
.text
);
226 defs
.extend(nested
.defs
.into_iter());
227 refs
.extend(nested
.refs
.into_iter());
230 if let hir
::FnRetTy
::Return(ref t
) = f
.decl
.output
{
231 text
.push_str(" -> ");
232 let nested
= t
.make(offset
+ text
.len(), None
, scx
)?
;
233 text
.push_str(&nested
.text
);
235 defs
.extend(nested
.defs
.into_iter());
236 refs
.extend(nested
.refs
.into_iter());
239 Ok(Signature { text, defs, refs }
)
241 hir
::TyKind
::Path(hir
::QPath
::Resolved(None
, ref path
)) => path
.make(offset
, id
, scx
),
242 hir
::TyKind
::Path(hir
::QPath
::Resolved(Some(ref qself
), ref path
)) => {
243 let nested_ty
= qself
.make(offset
+ 1, id
, scx
)?
;
244 let prefix
= format
!(
247 path_segment_to_string(&path
.segments
[0])
250 let name
= path_segment_to_string(path
.segments
.last().ok_or("Bad path")?
);
251 let res
= scx
.get_path_res(id
.ok_or("Missing id for Path")?
);
252 let id
= id_from_def_id(res
.def_id());
253 if path
.segments
.len() == 2 {
254 let start
= offset
+ prefix
.len();
255 let end
= start
+ name
.len();
258 text
: prefix
+ &name
,
260 refs
: vec
![SigElement { id, start, end }
],
263 let start
= offset
+ prefix
.len() + 5;
264 let end
= start
+ name
.len();
265 // FIXME should put the proper path in there, not ellipsis.
267 text
: prefix
+ "...::" + &name
,
269 refs
: vec
![SigElement { id, start, end }
],
273 hir
::TyKind
::Path(hir
::QPath
::TypeRelative(ty
, segment
)) => {
274 let nested_ty
= ty
.make(offset
+ 1, id
, scx
)?
;
275 let prefix
= format
!("<{}>::", nested_ty
.text
);
277 let name
= path_segment_to_string(segment
);
278 let res
= scx
.get_path_res(id
.ok_or("Missing id for Path")?
);
279 let id
= id_from_def_id(res
.def_id());
281 let start
= offset
+ prefix
.len();
282 let end
= start
+ name
.len();
284 text
: prefix
+ &name
,
286 refs
: vec
![SigElement { id, start, end }
],
289 hir
::TyKind
::Path(hir
::QPath
::LangItem(lang_item
, _
, _
)) => {
290 Ok(text_sig(format
!("#[lang = \"{}\"]", lang_item
.name())))
292 hir
::TyKind
::TraitObject(bounds
, ..) => {
293 // FIXME recurse into bounds
294 let bounds
: Vec
<hir
::GenericBound
<'_
>> = bounds
296 .map(|hir
::PolyTraitRef { bound_generic_params, trait_ref, span }
| {
297 hir
::GenericBound
::Trait(
299 bound_generic_params
,
300 trait_ref
: hir
::TraitRef
{
301 path
: trait_ref
.path
,
302 hir_ref_id
: trait_ref
.hir_ref_id
,
306 hir
::TraitBoundModifier
::None
,
310 let nested
= bounds_to_string(&bounds
);
313 hir
::TyKind
::Array(ref ty
, ref length
) => {
314 let nested_ty
= ty
.make(offset
+ 1, id
, scx
)?
;
315 let expr
= id_to_string(&scx
.tcx
.hir(), length
.hir_id()).replace('
\n'
, " ");
316 let text
= format
!("[{}; {}]", nested_ty
.text
, expr
);
317 Ok(replace_text(nested_ty
, text
))
319 hir
::TyKind
::OpaqueDef(item_id
, _
, _
) => {
320 let item
= scx
.tcx
.hir().item(item_id
);
321 item
.make(offset
, Some(item_id
.hir_id()), scx
)
323 hir
::TyKind
::Typeof(_
) | hir
::TyKind
::Infer
| hir
::TyKind
::Err
=> Err("Ty"),
328 impl<'hir
> Sig
for hir
::Item
<'hir
> {
329 fn make(&self, offset
: usize, _parent_id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
{
330 let id
= Some(self.hir_id());
333 hir
::ItemKind
::Static(ref ty
, m
, ref body
) => {
334 let mut text
= "static ".to_owned();
336 text
.push_str("mut ");
338 let name
= self.ident
.to_string();
339 let defs
= vec
![SigElement
{
340 id
: id_from_def_id(self.owner_id
.to_def_id()),
341 start
: offset
+ text
.len(),
342 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
);
350 text
.push_str(" = ");
351 let expr
= id_to_string(&scx
.tcx
.hir(), body
.hir_id
).replace('
\n'
, " ");
352 text
.push_str(&expr
);
356 Ok(extend_sig(ty
, text
, defs
, vec
![]))
358 hir
::ItemKind
::Const(ref ty
, ref body
) => {
359 let mut text
= "const ".to_owned();
360 let name
= self.ident
.to_string();
361 let defs
= vec
![SigElement
{
362 id
: id_from_def_id(self.owner_id
.to_def_id()),
363 start
: offset
+ text
.len(),
364 end
: offset
+ text
.len() + name
.len(),
366 text
.push_str(&name
);
369 let ty
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
370 text
.push_str(&ty
.text
);
372 text
.push_str(" = ");
373 let expr
= id_to_string(&scx
.tcx
.hir(), body
.hir_id
).replace('
\n'
, " ");
374 text
.push_str(&expr
);
378 Ok(extend_sig(ty
, text
, defs
, vec
![]))
380 hir
::ItemKind
::Fn(hir
::FnSig { ref decl, header, span: _ }
, ref generics
, _
) => {
381 let mut text
= String
::new();
382 if let hir
::Constness
::Const
= header
.constness
{
383 text
.push_str("const ");
385 if hir
::IsAsync
::Async
== header
.asyncness
{
386 text
.push_str("async ");
388 if let hir
::Unsafety
::Unsafe
= header
.unsafety
{
389 text
.push_str("unsafe ");
391 text
.push_str("fn ");
394 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
397 for i
in decl
.inputs
{
398 // FIXME should descend into patterns to add defs.
399 sig
.text
.push_str(": ");
400 let nested
= i
.make(offset
+ sig
.text
.len(), Some(i
.hir_id
), scx
)?
;
401 sig
.text
.push_str(&nested
.text
);
403 sig
.defs
.extend(nested
.defs
.into_iter());
404 sig
.refs
.extend(nested
.refs
.into_iter());
408 if let hir
::FnRetTy
::Return(ref t
) = decl
.output
{
409 sig
.text
.push_str(" -> ");
410 let nested
= t
.make(offset
+ sig
.text
.len(), None
, scx
)?
;
411 sig
.text
.push_str(&nested
.text
);
412 sig
.defs
.extend(nested
.defs
.into_iter());
413 sig
.refs
.extend(nested
.refs
.into_iter());
415 sig
.text
.push_str(" {}");
419 hir
::ItemKind
::Macro(..) => {
420 let mut text
= "macro".to_owned();
421 let name
= self.ident
.to_string();
422 text
.push_str(&name
);
423 text
.push_str(&"! {}");
427 hir
::ItemKind
::Mod(ref _mod
) => {
428 let mut text
= "mod ".to_owned();
429 let name
= self.ident
.to_string();
430 let defs
= vec
![SigElement
{
431 id
: id_from_def_id(self.owner_id
.to_def_id()),
432 start
: offset
+ text
.len(),
433 end
: offset
+ text
.len() + name
.len(),
435 text
.push_str(&name
);
436 // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
439 Ok(Signature { text, defs, refs: vec![] }
)
441 hir
::ItemKind
::TyAlias(ref ty
, ref generics
) => {
442 let text
= "type ".to_owned();
444 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
446 sig
.text
.push_str(" = ");
447 let ty
= ty
.make(offset
+ sig
.text
.len(), id
, scx
)?
;
448 sig
.text
.push_str(&ty
.text
);
451 Ok(merge_sigs(sig
.text
.clone(), vec
![sig
, ty
]))
453 hir
::ItemKind
::Enum(_
, ref generics
) => {
454 let text
= "enum ".to_owned();
456 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
457 sig
.text
.push_str(" {}");
460 hir
::ItemKind
::Struct(_
, ref generics
) => {
461 let text
= "struct ".to_owned();
463 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
464 sig
.text
.push_str(" {}");
467 hir
::ItemKind
::Union(_
, ref generics
) => {
468 let text
= "union ".to_owned();
470 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
471 sig
.text
.push_str(" {}");
474 hir
::ItemKind
::Trait(is_auto
, unsafety
, ref generics
, bounds
, _
) => {
475 let mut text
= String
::new();
477 if is_auto
== hir
::IsAuto
::Yes
{
478 text
.push_str("auto ");
481 if let hir
::Unsafety
::Unsafe
= unsafety
{
482 text
.push_str("unsafe ");
484 text
.push_str("trait ");
486 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
488 if !bounds
.is_empty() {
489 sig
.text
.push_str(": ");
490 sig
.text
.push_str(&bounds_to_string(bounds
));
492 // FIXME where clause
493 sig
.text
.push_str(" {}");
497 hir
::ItemKind
::TraitAlias(ref generics
, bounds
) => {
498 let mut text
= String
::new();
499 text
.push_str("trait ");
501 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
503 if !bounds
.is_empty() {
504 sig
.text
.push_str(" = ");
505 sig
.text
.push_str(&bounds_to_string(bounds
));
507 // FIXME where clause
512 hir
::ItemKind
::Impl(hir
::Impl
{
523 let mut text
= String
::new();
524 if let hir
::Defaultness
::Default { .. }
= defaultness
{
525 text
.push_str("default ");
527 if let hir
::Unsafety
::Unsafe
= unsafety
{
528 text
.push_str("unsafe ");
530 text
.push_str("impl");
531 if let hir
::Constness
::Const
= constness
{
532 text
.push_str(" const");
535 let generics_sig
= generics
.make(offset
+ text
.len(), id
, scx
)?
;
536 text
.push_str(&generics_sig
.text
);
540 let trait_sig
= if let Some(ref t
) = *of_trait
{
541 if let hir
::ImplPolarity
::Negative(_
) = polarity
{
544 let trait_sig
= t
.path
.make(offset
+ text
.len(), id
, scx
)?
;
545 text
.push_str(&trait_sig
.text
);
546 text
.push_str(" for ");
549 text_sig(String
::new())
552 let ty_sig
= self_ty
.make(offset
+ text
.len(), id
, scx
)?
;
553 text
.push_str(&ty_sig
.text
);
555 text
.push_str(" {}");
557 Ok(merge_sigs(text
, vec
![generics_sig
, trait_sig
, ty_sig
]))
559 // FIXME where clause
561 hir
::ItemKind
::ForeignMod { .. }
=> Err("extern mod"),
562 hir
::ItemKind
::GlobalAsm(_
) => Err("global asm"),
563 hir
::ItemKind
::ExternCrate(_
) => Err("extern crate"),
564 hir
::ItemKind
::OpaqueTy(ref opaque
) => {
566 Err("opaque type in trait")
571 // FIXME should implement this (e.g., pub use).
572 hir
::ItemKind
::Use(..) => Err("import"),
577 impl<'hir
> Sig
for hir
::Path
<'hir
> {
578 fn make(&self, offset
: usize, id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
{
579 let res
= scx
.get_path_res(id
.ok_or("Missing id for Path")?
);
581 let (name
, start
, end
) = match res
{
582 Res
::PrimTy(..) | Res
::SelfTyParam { .. }
| Res
::SelfTyAlias { .. }
| Res
::Err
=> {
583 return Ok(Signature { text: path_to_string(self), defs: vec![], refs: vec![] }
);
585 Res
::Def(DefKind
::AssocConst
| DefKind
::Variant
| DefKind
::Ctor(..), _
) => {
586 let len
= self.segments
.len();
588 return Err("Bad path");
590 // FIXME: really we should descend into the generics here and add SigElements for
592 // FIXME: would be nice to have a def for the first path segment.
593 let seg1
= path_segment_to_string(&self.segments
[len
- 2]);
594 let seg2
= path_segment_to_string(&self.segments
[len
- 1]);
595 let start
= offset
+ seg1
.len() + 2;
596 (format
!("{}::{}", seg1
, seg2
), start
, start
+ seg2
.len())
599 let name
= path_segment_to_string(self.segments
.last().ok_or("Bad path")?
);
600 let end
= offset
+ name
.len();
605 let id
= id_from_def_id(res
.def_id());
606 Ok(Signature { text: name, defs: vec![], refs: vec![SigElement { id, start, end }
] })
610 // This does not cover the where clause, which must be processed separately.
611 impl<'hir
> Sig
for hir
::Generics
<'hir
> {
612 fn make(&self, offset
: usize, _parent_id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
{
613 if self.params
.is_empty() {
614 return Ok(text_sig(String
::new()));
617 let mut text
= "<".to_owned();
619 let mut defs
= Vec
::with_capacity(self.params
.len());
620 for param
in self.params
{
621 let mut param_text
= String
::new();
622 if let hir
::GenericParamKind
::Const { .. }
= param
.kind
{
623 param_text
.push_str("const ");
625 param_text
.push_str(param
.name
.ident().as_str());
626 defs
.push(SigElement
{
627 id
: id_from_hir_id(param
.hir_id
, scx
),
628 start
: offset
+ text
.len(),
629 end
: offset
+ text
.len() + param_text
.as_str().len(),
631 if let hir
::GenericParamKind
::Const { ref ty, default }
= param
.kind
{
632 param_text
.push_str(": ");
633 param_text
.push_str(&ty_to_string(&ty
));
634 if let Some(default) = default {
635 param_text
.push_str(" = ");
636 param_text
.push_str(&id_to_string(&scx
.tcx
.hir(), default.hir_id
));
639 text
.push_str(¶m_text
);
644 Ok(Signature { text, defs, refs: vec![] }
)
648 impl<'hir
> Sig
for hir
::FieldDef
<'hir
> {
649 fn make(&self, offset
: usize, _parent_id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
{
650 let mut text
= String
::new();
652 text
.push_str(&self.ident
.to_string());
653 let defs
= Some(SigElement
{
654 id
: id_from_hir_id(self.hir_id
, scx
),
656 end
: offset
+ text
.len(),
660 let mut ty_sig
= self.ty
.make(offset
+ text
.len(), Some(self.hir_id
), scx
)?
;
661 text
.push_str(&ty_sig
.text
);
663 ty_sig
.defs
.extend(defs
.into_iter());
668 impl<'hir
> Sig
for hir
::Variant
<'hir
> {
669 fn make(&self, offset
: usize, parent_id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
{
670 let mut text
= self.ident
.to_string();
672 hir
::VariantData
::Struct(fields
, r
) => {
673 let id
= parent_id
.ok_or("Missing id for Variant's parent")?
;
674 let name_def
= SigElement
{
675 id
: id_from_hir_id(id
, scx
),
677 end
: offset
+ text
.len(),
679 text
.push_str(" { ");
680 let mut defs
= vec
![name_def
];
681 let mut refs
= vec
![];
683 text
.push_str("/* parse error */ ");
686 let field_sig
= f
.make(offset
+ text
.len(), Some(id
), scx
)?
;
687 text
.push_str(&field_sig
.text
);
689 defs
.extend(field_sig
.defs
.into_iter());
690 refs
.extend(field_sig
.refs
.into_iter());
694 Ok(Signature { text, defs, refs }
)
696 hir
::VariantData
::Tuple(fields
, id
, _
) => {
697 let name_def
= SigElement
{
698 id
: id_from_hir_id(id
, scx
),
700 end
: offset
+ text
.len(),
703 let mut defs
= vec
![name_def
];
704 let mut refs
= vec
![];
706 let field_sig
= f
.make(offset
+ text
.len(), Some(id
), scx
)?
;
707 text
.push_str(&field_sig
.text
);
709 defs
.extend(field_sig
.defs
.into_iter());
710 refs
.extend(field_sig
.refs
.into_iter());
713 Ok(Signature { text, defs, refs }
)
715 hir
::VariantData
::Unit(id
, _
) => {
716 let name_def
= SigElement
{
717 id
: id_from_hir_id(id
, scx
),
719 end
: offset
+ text
.len(),
721 Ok(Signature { text, defs: vec![name_def], refs: vec![] }
)
727 impl<'hir
> Sig
for hir
::ForeignItem
<'hir
> {
728 fn make(&self, offset
: usize, _parent_id
: Option
<hir
::HirId
>, scx
: &SaveContext
<'_
>) -> Result
{
729 let id
= Some(self.hir_id());
731 hir
::ForeignItemKind
::Fn(decl
, _
, ref generics
) => {
732 let mut text
= String
::new();
733 text
.push_str("fn ");
736 name_and_generics(text
, offset
, generics
, self.hir_id(), self.ident
, scx
)?
;
739 for i
in decl
.inputs
{
740 sig
.text
.push_str(": ");
741 let nested
= i
.make(offset
+ sig
.text
.len(), Some(i
.hir_id
), scx
)?
;
742 sig
.text
.push_str(&nested
.text
);
744 sig
.defs
.extend(nested
.defs
.into_iter());
745 sig
.refs
.extend(nested
.refs
.into_iter());
749 if let hir
::FnRetTy
::Return(ref t
) = decl
.output
{
750 sig
.text
.push_str(" -> ");
751 let nested
= t
.make(offset
+ sig
.text
.len(), None
, scx
)?
;
752 sig
.text
.push_str(&nested
.text
);
753 sig
.defs
.extend(nested
.defs
.into_iter());
754 sig
.refs
.extend(nested
.refs
.into_iter());
760 hir
::ForeignItemKind
::Static(ref ty
, m
) => {
761 let mut text
= "static ".to_owned();
762 if m
== Mutability
::Mut
{
763 text
.push_str("mut ");
765 let name
= self.ident
.to_string();
766 let defs
= vec
![SigElement
{
767 id
: id_from_def_id(self.owner_id
.to_def_id()),
768 start
: offset
+ text
.len(),
769 end
: offset
+ text
.len() + name
.len(),
771 text
.push_str(&name
);
774 let ty_sig
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
777 Ok(extend_sig(ty_sig
, text
, defs
, vec
![]))
779 hir
::ForeignItemKind
::Type
=> {
780 let mut text
= "type ".to_owned();
781 let name
= self.ident
.to_string();
782 let defs
= vec
![SigElement
{
783 id
: id_from_def_id(self.owner_id
.to_def_id()),
784 start
: offset
+ text
.len(),
785 end
: offset
+ text
.len() + name
.len(),
787 text
.push_str(&name
);
790 Ok(Signature { text, defs, refs: vec![] }
)
796 fn name_and_generics(
799 generics
: &hir
::Generics
<'_
>,
802 scx
: &SaveContext
<'_
>,
804 let name
= name
.to_string();
805 let def
= SigElement
{
806 id
: id_from_hir_id(id
, scx
),
807 start
: offset
+ text
.len(),
808 end
: offset
+ text
.len() + name
.len(),
810 text
.push_str(&name
);
811 let generics
: Signature
= generics
.make(offset
+ text
.len(), Some(id
), scx
)?
;
812 // FIXME where clause
813 let text
= format
!("{}{}", text
, generics
.text
);
814 Ok(extend_sig(generics
, text
, vec
![def
], vec
![]))
817 fn make_assoc_type_signature(
820 bounds
: Option
<hir
::GenericBounds
<'_
>>,
821 default: Option
<&hir
::Ty
<'_
>>,
822 scx
: &SaveContext
<'_
>,
824 let mut text
= "type ".to_owned();
825 let name
= ident
.to_string();
826 let mut defs
= vec
![SigElement
{
827 id
: id_from_hir_id(id
, scx
),
829 end
: text
.len() + name
.len(),
831 let mut refs
= vec
![];
832 text
.push_str(&name
);
833 if let Some(bounds
) = bounds
{
835 // FIXME should descend into bounds
836 text
.push_str(&bounds_to_string(bounds
));
838 if let Some(default) = default {
839 text
.push_str(" = ");
840 let ty_sig
= default.make(text
.len(), Some(id
), scx
)?
;
841 text
.push_str(&ty_sig
.text
);
842 defs
.extend(ty_sig
.defs
.into_iter());
843 refs
.extend(ty_sig
.refs
.into_iter());
846 Ok(Signature { text, defs, refs }
)
849 fn make_assoc_const_signature(
853 default: Option
<&hir
::Expr
<'_
>>,
854 scx
: &SaveContext
<'_
>,
856 let mut text
= "const ".to_owned();
857 let name
= ident
.to_string();
858 let mut defs
= vec
![SigElement
{
859 id
: id_from_hir_id(id
, scx
),
861 end
: text
.len() + name
.len(),
863 let mut refs
= vec
![];
864 text
.push_str(&name
);
867 let ty_sig
= ty
.make(text
.len(), Some(id
), scx
)?
;
868 text
.push_str(&ty_sig
.text
);
869 defs
.extend(ty_sig
.defs
.into_iter());
870 refs
.extend(ty_sig
.refs
.into_iter());
872 if let Some(default) = default {
873 text
.push_str(" = ");
874 text
.push_str(&id_to_string(&scx
.tcx
.hir(), default.hir_id
));
877 Ok(Signature { text, defs, refs }
)
880 fn make_method_signature(
883 generics
: &hir
::Generics
<'_
>,
885 scx
: &SaveContext
<'_
>,
887 // FIXME code dup with function signature
888 let mut text
= String
::new();
889 if let hir
::Constness
::Const
= m
.header
.constness
{
890 text
.push_str("const ");
892 if hir
::IsAsync
::Async
== m
.header
.asyncness
{
893 text
.push_str("async ");
895 if let hir
::Unsafety
::Unsafe
= m
.header
.unsafety
{
896 text
.push_str("unsafe ");
898 text
.push_str("fn ");
900 let mut sig
= name_and_generics(text
, 0, generics
, id
, ident
, scx
)?
;
903 for i
in m
.decl
.inputs
{
904 sig
.text
.push_str(": ");
905 let nested
= i
.make(sig
.text
.len(), Some(i
.hir_id
), scx
)?
;
906 sig
.text
.push_str(&nested
.text
);
908 sig
.defs
.extend(nested
.defs
.into_iter());
909 sig
.refs
.extend(nested
.refs
.into_iter());
913 if let hir
::FnRetTy
::Return(ref t
) = m
.decl
.output
{
914 sig
.text
.push_str(" -> ");
915 let nested
= t
.make(sig
.text
.len(), None
, scx
)?
;
916 sig
.text
.push_str(&nested
.text
);
917 sig
.defs
.extend(nested
.defs
.into_iter());
918 sig
.refs
.extend(nested
.refs
.into_iter());
920 sig
.text
.push_str(" {}");