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_ast
::ast
::{self, Extern, NodeId}
;
33 use rustc_ast_pretty
::pprust
;
34 use rustc_hir
::def
::{DefKind, Res}
;
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 { text, defs: vec![], refs: vec![] }
;
135 let (defs
, refs
): (Vec
<_
>, Vec
<_
>) = sigs
.into_iter().map(|s
| (s
.defs
, s
.refs
)).unzip();
137 result
.defs
.extend(defs
.into_iter().flat_map(|ds
| ds
.into_iter()));
138 result
.refs
.extend(refs
.into_iter().flat_map(|rs
| rs
.into_iter()));
143 fn text_sig(text
: String
) -> Signature
{
144 Signature { text, defs: vec![], refs: vec![] }
147 fn push_extern(text
: &mut String
, ext
: Extern
) {
150 Extern
::Implicit
=> text
.push_str("extern "),
151 Extern
::Explicit(abi
) => text
.push_str(&format
!("extern \"{}\" ", abi
.symbol
)),
155 impl Sig
for ast
::Ty
{
156 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
157 let id
= Some(self.id
);
159 ast
::TyKind
::Slice(ref ty
) => {
160 let nested
= ty
.make(offset
+ 1, id
, scx
)?
;
161 let text
= format
!("[{}]", nested
.text
);
162 Ok(replace_text(nested
, text
))
164 ast
::TyKind
::Ptr(ref mt
) => {
165 let prefix
= match mt
.mutbl
{
166 ast
::Mutability
::Mut
=> "*mut ",
167 ast
::Mutability
::Not
=> "*const ",
169 let nested
= mt
.ty
.make(offset
+ prefix
.len(), id
, scx
)?
;
170 let text
= format
!("{}{}", prefix
, nested
.text
);
171 Ok(replace_text(nested
, text
))
173 ast
::TyKind
::Rptr(ref lifetime
, ref mt
) => {
174 let mut prefix
= "&".to_owned();
175 if let &Some(ref l
) = lifetime
{
176 prefix
.push_str(&l
.ident
.to_string());
179 if let ast
::Mutability
::Mut
= mt
.mutbl
{
180 prefix
.push_str("mut ");
183 let nested
= mt
.ty
.make(offset
+ prefix
.len(), id
, scx
)?
;
184 let text
= format
!("{}{}", prefix
, nested
.text
);
185 Ok(replace_text(nested
, text
))
187 ast
::TyKind
::Never
=> Ok(text_sig("!".to_owned())),
188 ast
::TyKind
::CVarArgs
=> Ok(text_sig("...".to_owned())),
189 ast
::TyKind
::Tup(ref ts
) => {
190 let mut text
= "(".to_owned();
191 let mut defs
= vec
![];
192 let mut refs
= vec
![];
194 let nested
= t
.make(offset
+ text
.len(), id
, scx
)?
;
195 text
.push_str(&nested
.text
);
197 defs
.extend(nested
.defs
.into_iter());
198 refs
.extend(nested
.refs
.into_iter());
201 Ok(Signature { text, defs, refs }
)
203 ast
::TyKind
::Paren(ref ty
) => {
204 let nested
= ty
.make(offset
+ 1, id
, scx
)?
;
205 let text
= format
!("({})", nested
.text
);
206 Ok(replace_text(nested
, text
))
208 ast
::TyKind
::BareFn(ref f
) => {
209 let mut text
= String
::new();
210 if !f
.generic_params
.is_empty() {
211 // FIXME defs, bounds on lifetimes
212 text
.push_str("for<");
216 .filter_map(|param
| match param
.kind
{
217 ast
::GenericParamKind
::Lifetime { .. }
=> {
218 Some(param
.ident
.to_string())
228 if let ast
::Unsafe
::Yes(_
) = f
.unsafety
{
229 text
.push_str("unsafe ");
231 push_extern(&mut text
, f
.ext
);
232 text
.push_str("fn(");
234 let mut defs
= vec
![];
235 let mut refs
= vec
![];
236 for i
in &f
.decl
.inputs
{
237 let nested
= i
.ty
.make(offset
+ text
.len(), Some(i
.id
), scx
)?
;
238 text
.push_str(&nested
.text
);
240 defs
.extend(nested
.defs
.into_iter());
241 refs
.extend(nested
.refs
.into_iter());
244 if let ast
::FnRetTy
::Ty(ref t
) = f
.decl
.output
{
245 text
.push_str(" -> ");
246 let nested
= t
.make(offset
+ text
.len(), None
, scx
)?
;
247 text
.push_str(&nested
.text
);
249 defs
.extend(nested
.defs
.into_iter());
250 refs
.extend(nested
.refs
.into_iter());
253 Ok(Signature { text, defs, refs }
)
255 ast
::TyKind
::Path(None
, ref path
) => path
.make(offset
, id
, scx
),
256 ast
::TyKind
::Path(Some(ref qself
), ref path
) => {
257 let nested_ty
= qself
.ty
.make(offset
+ 1, id
, scx
)?
;
258 let prefix
= if qself
.position
== 0 {
259 format
!("<{}>::", nested_ty
.text
)
260 } else if qself
.position
== 1 {
261 let first
= pprust
::path_segment_to_string(&path
.segments
[0]);
262 format
!("<{} as {}>::", nested_ty
.text
, first
)
264 // FIXME handle path instead of elipses.
265 format
!("<{} as ...>::", nested_ty
.text
)
268 let name
= pprust
::path_segment_to_string(path
.segments
.last().ok_or("Bad path")?
);
269 let res
= scx
.get_path_res(id
.ok_or("Missing id for Path")?
);
270 let id
= id_from_def_id(res
.def_id());
271 if path
.segments
.len() - qself
.position
== 1 {
272 let start
= offset
+ prefix
.len();
273 let end
= start
+ name
.len();
276 text
: prefix
+ &name
,
278 refs
: vec
![SigElement { id, start, end }
],
281 let start
= offset
+ prefix
.len() + 5;
282 let end
= start
+ name
.len();
283 // FIXME should put the proper path in there, not elipses.
285 text
: prefix
+ "...::" + &name
,
287 refs
: vec
![SigElement { id, start, end }
],
291 ast
::TyKind
::TraitObject(ref bounds
, ..) => {
292 // FIXME recurse into bounds
293 let nested
= pprust
::bounds_to_string(bounds
);
296 ast
::TyKind
::ImplTrait(_
, ref bounds
) => {
297 // FIXME recurse into bounds
298 let nested
= pprust
::bounds_to_string(bounds
);
299 Ok(text_sig(format
!("impl {}", nested
)))
301 ast
::TyKind
::Array(ref ty
, ref v
) => {
302 let nested_ty
= ty
.make(offset
+ 1, id
, scx
)?
;
303 let expr
= pprust
::expr_to_string(&v
.value
).replace('
\n'
, " ");
304 let text
= format
!("[{}; {}]", nested_ty
.text
, expr
);
305 Ok(replace_text(nested_ty
, text
))
307 ast
::TyKind
::Typeof(_
)
310 | ast
::TyKind
::ImplicitSelf
311 | ast
::TyKind
::MacCall(_
) => Err("Ty"),
316 impl Sig
for ast
::Item
{
317 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
318 let id
= Some(self.id
);
321 ast
::ItemKind
::Static(ref ty
, m
, ref expr
) => {
322 let mut text
= "static ".to_owned();
323 if m
== ast
::Mutability
::Mut
{
324 text
.push_str("mut ");
326 let name
= self.ident
.to_string();
327 let defs
= vec
![SigElement
{
328 id
: id_from_node_id(self.id
, scx
),
329 start
: offset
+ text
.len(),
330 end
: offset
+ text
.len() + name
.len(),
332 text
.push_str(&name
);
335 let ty
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
336 text
.push_str(&ty
.text
);
338 if let Some(expr
) = expr
{
339 text
.push_str(" = ");
340 let expr
= pprust
::expr_to_string(expr
).replace('
\n'
, " ");
341 text
.push_str(&expr
);
346 Ok(extend_sig(ty
, text
, defs
, vec
![]))
348 ast
::ItemKind
::Const(_
, ref ty
, ref expr
) => {
349 let mut text
= "const ".to_owned();
350 let name
= self.ident
.to_string();
351 let defs
= vec
![SigElement
{
352 id
: id_from_node_id(self.id
, scx
),
353 start
: offset
+ text
.len(),
354 end
: offset
+ text
.len() + name
.len(),
356 text
.push_str(&name
);
359 let ty
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
360 text
.push_str(&ty
.text
);
362 if let Some(expr
) = expr
{
363 text
.push_str(" = ");
364 let expr
= pprust
::expr_to_string(expr
).replace('
\n'
, " ");
365 text
.push_str(&expr
);
370 Ok(extend_sig(ty
, text
, defs
, vec
![]))
372 ast
::ItemKind
::Fn(_
, ast
::FnSig { ref decl, header }
, ref generics
, _
) => {
373 let mut text
= String
::new();
374 if let ast
::Const
::Yes(_
) = header
.constness
{
375 text
.push_str("const ");
377 if header
.asyncness
.is_async() {
378 text
.push_str("async ");
380 if let ast
::Unsafe
::Yes(_
) = header
.unsafety
{
381 text
.push_str("unsafe ");
383 push_extern(&mut text
, header
.ext
);
384 text
.push_str("fn ");
386 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
389 for i
in &decl
.inputs
{
390 // FIXME should descend into patterns to add defs.
391 sig
.text
.push_str(&pprust
::pat_to_string(&i
.pat
));
392 sig
.text
.push_str(": ");
393 let nested
= i
.ty
.make(offset
+ sig
.text
.len(), Some(i
.id
), scx
)?
;
394 sig
.text
.push_str(&nested
.text
);
396 sig
.defs
.extend(nested
.defs
.into_iter());
397 sig
.refs
.extend(nested
.refs
.into_iter());
401 if let ast
::FnRetTy
::Ty(ref t
) = decl
.output
{
402 sig
.text
.push_str(" -> ");
403 let nested
= t
.make(offset
+ sig
.text
.len(), None
, scx
)?
;
404 sig
.text
.push_str(&nested
.text
);
405 sig
.defs
.extend(nested
.defs
.into_iter());
406 sig
.refs
.extend(nested
.refs
.into_iter());
408 sig
.text
.push_str(" {}");
412 ast
::ItemKind
::Mod(ref _mod
) => {
413 let mut text
= "mod ".to_owned();
414 let name
= self.ident
.to_string();
415 let defs
= vec
![SigElement
{
416 id
: id_from_node_id(self.id
, scx
),
417 start
: offset
+ text
.len(),
418 end
: offset
+ text
.len() + name
.len(),
420 text
.push_str(&name
);
421 // Could be either `mod foo;` or `mod foo { ... }`, but we'll just pick one.
424 Ok(Signature { text, defs, refs: vec![] }
)
426 ast
::ItemKind
::TyAlias(_
, ref generics
, _
, ref ty
) => {
427 let text
= "type ".to_owned();
428 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
430 sig
.text
.push_str(" = ");
432 Some(ty
) => ty
.make(offset
+ sig
.text
.len(), id
, scx
)?
,
433 None
=> return Err("Ty"),
435 sig
.text
.push_str(&ty
.text
);
438 Ok(merge_sigs(sig
.text
.clone(), vec
![sig
, ty
]))
440 ast
::ItemKind
::Enum(_
, ref generics
) => {
441 let text
= "enum ".to_owned();
442 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
443 sig
.text
.push_str(" {}");
446 ast
::ItemKind
::Struct(_
, ref generics
) => {
447 let text
= "struct ".to_owned();
448 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
449 sig
.text
.push_str(" {}");
452 ast
::ItemKind
::Union(_
, ref generics
) => {
453 let text
= "union ".to_owned();
454 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
455 sig
.text
.push_str(" {}");
458 ast
::ItemKind
::Trait(is_auto
, unsafety
, ref generics
, ref bounds
, _
) => {
459 let mut text
= String
::new();
461 if is_auto
== ast
::IsAuto
::Yes
{
462 text
.push_str("auto ");
465 if let ast
::Unsafe
::Yes(_
) = unsafety
{
466 text
.push_str("unsafe ");
468 text
.push_str("trait ");
469 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
471 if !bounds
.is_empty() {
472 sig
.text
.push_str(": ");
473 sig
.text
.push_str(&pprust
::bounds_to_string(bounds
));
475 // FIXME where clause
476 sig
.text
.push_str(" {}");
480 ast
::ItemKind
::TraitAlias(ref generics
, ref bounds
) => {
481 let mut text
= String
::new();
482 text
.push_str("trait ");
483 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
485 if !bounds
.is_empty() {
486 sig
.text
.push_str(" = ");
487 sig
.text
.push_str(&pprust
::bounds_to_string(bounds
));
489 // FIXME where clause
490 sig
.text
.push_str(";");
494 ast
::ItemKind
::Impl
{
504 let mut text
= String
::new();
505 if let ast
::Defaultness
::Default(_
) = defaultness
{
506 text
.push_str("default ");
508 if let ast
::Unsafe
::Yes(_
) = unsafety
{
509 text
.push_str("unsafe ");
511 text
.push_str("impl");
512 if let ast
::Const
::Yes(_
) = constness
{
513 text
.push_str(" const");
516 let generics_sig
= generics
.make(offset
+ text
.len(), id
, scx
)?
;
517 text
.push_str(&generics_sig
.text
);
521 let trait_sig
= if let Some(ref t
) = *of_trait
{
522 if let ast
::ImplPolarity
::Negative(_
) = polarity
{
525 let trait_sig
= t
.path
.make(offset
+ text
.len(), id
, scx
)?
;
526 text
.push_str(&trait_sig
.text
);
527 text
.push_str(" for ");
530 text_sig(String
::new())
533 let ty_sig
= self_ty
.make(offset
+ text
.len(), id
, scx
)?
;
534 text
.push_str(&ty_sig
.text
);
536 text
.push_str(" {}");
538 Ok(merge_sigs(text
, vec
![generics_sig
, trait_sig
, ty_sig
]))
540 // FIXME where clause
542 ast
::ItemKind
::ForeignMod(_
) => Err("extern mod"),
543 ast
::ItemKind
::GlobalAsm(_
) => Err("glboal asm"),
544 ast
::ItemKind
::ExternCrate(_
) => Err("extern crate"),
545 // FIXME should implement this (e.g., pub use).
546 ast
::ItemKind
::Use(_
) => Err("import"),
547 ast
::ItemKind
::MacCall(..) | ast
::ItemKind
::MacroDef(_
) => Err("Macro"),
552 impl Sig
for ast
::Path
{
553 fn make(&self, offset
: usize, id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
554 let res
= scx
.get_path_res(id
.ok_or("Missing id for Path")?
);
556 let (name
, start
, end
) = match res
{
557 Res
::PrimTy(..) | Res
::SelfTy(..) | Res
::Err
=> {
558 return Ok(Signature
{
559 text
: pprust
::path_to_string(self),
564 Res
::Def(DefKind
::AssocConst
| DefKind
::Variant
| DefKind
::Ctor(..), _
) => {
565 let len
= self.segments
.len();
567 return Err("Bad path");
569 // FIXME: really we should descend into the generics here and add SigElements for
571 // FIXME: would be nice to have a def for the first path segment.
572 let seg1
= pprust
::path_segment_to_string(&self.segments
[len
- 2]);
573 let seg2
= pprust
::path_segment_to_string(&self.segments
[len
- 1]);
574 let start
= offset
+ seg1
.len() + 2;
575 (format
!("{}::{}", seg1
, seg2
), start
, start
+ seg2
.len())
578 let name
= pprust
::path_segment_to_string(self.segments
.last().ok_or("Bad path")?
);
579 let end
= offset
+ name
.len();
584 let id
= id_from_def_id(res
.def_id());
585 Ok(Signature { text: name, defs: vec![], refs: vec![SigElement { id, start, end }
] })
589 // This does not cover the where clause, which must be processed separately.
590 impl Sig
for ast
::Generics
{
591 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
592 if self.params
.is_empty() {
593 return Ok(text_sig(String
::new()));
596 let mut text
= "<".to_owned();
598 let mut defs
= Vec
::with_capacity(self.params
.len());
599 for param
in &self.params
{
600 let mut param_text
= String
::new();
601 if let ast
::GenericParamKind
::Const { .. }
= param
.kind
{
602 param_text
.push_str("const ");
604 param_text
.push_str(¶m
.ident
.as_str());
605 defs
.push(SigElement
{
606 id
: id_from_node_id(param
.id
, scx
),
607 start
: offset
+ text
.len(),
608 end
: offset
+ text
.len() + param_text
.as_str().len(),
610 if let ast
::GenericParamKind
::Const { ref ty }
= param
.kind
{
611 param_text
.push_str(": ");
612 param_text
.push_str(&pprust
::ty_to_string(&ty
));
614 if !param
.bounds
.is_empty() {
615 param_text
.push_str(": ");
617 ast
::GenericParamKind
::Lifetime { .. }
=> {
621 .map(|bound
| match bound
{
622 ast
::GenericBound
::Outlives(lt
) => lt
.ident
.to_string(),
627 param_text
.push_str(&bounds
);
628 // FIXME add lifetime bounds refs.
630 ast
::GenericParamKind
::Type { .. }
=> {
631 param_text
.push_str(&pprust
::bounds_to_string(¶m
.bounds
));
632 // FIXME descend properly into bounds.
634 ast
::GenericParamKind
::Const { .. }
=> {
635 // Const generics cannot contain bounds.
639 text
.push_str(¶m_text
);
644 Ok(Signature { text, defs, refs: vec![] }
)
648 impl Sig
for ast
::StructField
{
649 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
650 let mut text
= String
::new();
652 if let Some(ident
) = self.ident
{
653 text
.push_str(&ident
.to_string());
654 defs
= Some(SigElement
{
655 id
: id_from_node_id(self.id
, scx
),
657 end
: offset
+ text
.len(),
662 let mut ty_sig
= self.ty
.make(offset
+ text
.len(), Some(self.id
), scx
)?
;
663 text
.push_str(&ty_sig
.text
);
665 ty_sig
.defs
.extend(defs
.into_iter());
670 impl Sig
for ast
::Variant
{
671 fn make(&self, offset
: usize, parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
672 let mut text
= self.ident
.to_string();
674 ast
::VariantData
::Struct(ref fields
, r
) => {
675 let id
= parent_id
.unwrap();
676 let name_def
= SigElement
{
677 id
: id_from_node_id(id
, scx
),
679 end
: offset
+ text
.len(),
681 text
.push_str(" { ");
682 let mut defs
= vec
![name_def
];
683 let mut refs
= vec
![];
685 text
.push_str("/* parse error */ ");
688 let field_sig
= f
.make(offset
+ text
.len(), Some(id
), scx
)?
;
689 text
.push_str(&field_sig
.text
);
691 defs
.extend(field_sig
.defs
.into_iter());
692 refs
.extend(field_sig
.refs
.into_iter());
696 Ok(Signature { text, defs, refs }
)
698 ast
::VariantData
::Tuple(ref fields
, id
) => {
699 let name_def
= SigElement
{
700 id
: id_from_node_id(id
, scx
),
702 end
: offset
+ text
.len(),
705 let mut defs
= vec
![name_def
];
706 let mut refs
= vec
![];
708 let field_sig
= f
.make(offset
+ text
.len(), Some(id
), scx
)?
;
709 text
.push_str(&field_sig
.text
);
711 defs
.extend(field_sig
.defs
.into_iter());
712 refs
.extend(field_sig
.refs
.into_iter());
715 Ok(Signature { text, defs, refs }
)
717 ast
::VariantData
::Unit(id
) => {
718 let name_def
= SigElement
{
719 id
: id_from_node_id(id
, scx
),
721 end
: offset
+ text
.len(),
723 Ok(Signature { text, defs: vec![name_def], refs: vec![] }
)
729 impl Sig
for ast
::ForeignItem
{
730 fn make(&self, offset
: usize, _parent_id
: Option
<NodeId
>, scx
: &SaveContext
<'_
, '_
>) -> Result
{
731 let id
= Some(self.id
);
733 ast
::ForeignItemKind
::Fn(_
, ref sig
, ref generics
, _
) => {
734 let decl
= &sig
.decl
;
735 let mut text
= String
::new();
736 text
.push_str("fn ");
738 let mut sig
= name_and_generics(text
, offset
, generics
, self.id
, self.ident
, scx
)?
;
741 for i
in &decl
.inputs
{
742 // FIXME should descend into patterns to add defs.
743 sig
.text
.push_str(&pprust
::pat_to_string(&i
.pat
));
744 sig
.text
.push_str(": ");
745 let nested
= i
.ty
.make(offset
+ sig
.text
.len(), Some(i
.id
), scx
)?
;
746 sig
.text
.push_str(&nested
.text
);
748 sig
.defs
.extend(nested
.defs
.into_iter());
749 sig
.refs
.extend(nested
.refs
.into_iter());
753 if let ast
::FnRetTy
::Ty(ref t
) = decl
.output
{
754 sig
.text
.push_str(" -> ");
755 let nested
= t
.make(offset
+ sig
.text
.len(), None
, scx
)?
;
756 sig
.text
.push_str(&nested
.text
);
757 sig
.defs
.extend(nested
.defs
.into_iter());
758 sig
.refs
.extend(nested
.refs
.into_iter());
764 ast
::ForeignItemKind
::Static(ref ty
, m
, _
) => {
765 let mut text
= "static ".to_owned();
766 if m
== ast
::Mutability
::Mut
{
767 text
.push_str("mut ");
769 let name
= self.ident
.to_string();
770 let defs
= vec
![SigElement
{
771 id
: id_from_node_id(self.id
, scx
),
772 start
: offset
+ text
.len(),
773 end
: offset
+ text
.len() + name
.len(),
775 text
.push_str(&name
);
778 let ty_sig
= ty
.make(offset
+ text
.len(), id
, scx
)?
;
781 Ok(extend_sig(ty_sig
, text
, defs
, vec
![]))
783 ast
::ForeignItemKind
::TyAlias(..) => {
784 let mut text
= "type ".to_owned();
785 let name
= self.ident
.to_string();
786 let defs
= vec
![SigElement
{
787 id
: id_from_node_id(self.id
, scx
),
788 start
: offset
+ text
.len(),
789 end
: offset
+ text
.len() + name
.len(),
791 text
.push_str(&name
);
794 Ok(Signature { text, defs, refs: vec![] }
)
796 ast
::ForeignItemKind
::MacCall(..) => Err("macro"),
801 fn name_and_generics(
804 generics
: &ast
::Generics
,
807 scx
: &SaveContext
<'_
, '_
>,
809 let name
= name
.to_string();
810 let def
= SigElement
{
811 id
: id_from_node_id(id
, scx
),
812 start
: offset
+ text
.len(),
813 end
: offset
+ text
.len() + name
.len(),
815 text
.push_str(&name
);
816 let generics
: Signature
= generics
.make(offset
+ text
.len(), Some(id
), scx
)?
;
817 // FIXME where clause
818 let text
= format
!("{}{}", text
, generics
.text
);
819 Ok(extend_sig(generics
, text
, vec
![def
], vec
![]))
822 fn make_assoc_type_signature(
825 bounds
: Option
<&ast
::GenericBounds
>,
826 default: Option
<&ast
::Ty
>,
827 scx
: &SaveContext
<'_
, '_
>,
829 let mut text
= "type ".to_owned();
830 let name
= ident
.to_string();
831 let mut defs
= vec
![SigElement
{
832 id
: id_from_node_id(id
, scx
),
834 end
: text
.len() + name
.len(),
836 let mut refs
= vec
![];
837 text
.push_str(&name
);
838 if let Some(bounds
) = bounds
{
840 // FIXME should descend into bounds
841 text
.push_str(&pprust
::bounds_to_string(bounds
));
843 if let Some(default) = default {
844 text
.push_str(" = ");
845 let ty_sig
= default.make(text
.len(), Some(id
), scx
)?
;
846 text
.push_str(&ty_sig
.text
);
847 defs
.extend(ty_sig
.defs
.into_iter());
848 refs
.extend(ty_sig
.refs
.into_iter());
851 Ok(Signature { text, defs, refs }
)
854 fn make_assoc_const_signature(
858 default: Option
<&ast
::Expr
>,
859 scx
: &SaveContext
<'_
, '_
>,
861 let mut text
= "const ".to_owned();
862 let name
= ident
.to_string();
863 let mut defs
= vec
![SigElement
{
864 id
: id_from_node_id(id
, scx
),
866 end
: text
.len() + name
.len(),
868 let mut refs
= vec
![];
869 text
.push_str(&name
);
872 let ty_sig
= ty
.make(text
.len(), Some(id
), scx
)?
;
873 text
.push_str(&ty_sig
.text
);
874 defs
.extend(ty_sig
.defs
.into_iter());
875 refs
.extend(ty_sig
.refs
.into_iter());
877 if let Some(default) = default {
878 text
.push_str(" = ");
879 text
.push_str(&pprust
::expr_to_string(default));
882 Ok(Signature { text, defs, refs }
)
885 fn make_method_signature(
888 generics
: &ast
::Generics
,
890 scx
: &SaveContext
<'_
, '_
>,
892 // FIXME code dup with function signature
893 let mut text
= String
::new();
894 if let ast
::Const
::Yes(_
) = m
.header
.constness
{
895 text
.push_str("const ");
897 if m
.header
.asyncness
.is_async() {
898 text
.push_str("async ");
900 if let ast
::Unsafe
::Yes(_
) = m
.header
.unsafety
{
901 text
.push_str("unsafe ");
903 push_extern(&mut text
, m
.header
.ext
);
904 text
.push_str("fn ");
906 let mut sig
= name_and_generics(text
, 0, generics
, id
, ident
, scx
)?
;
909 for i
in &m
.decl
.inputs
{
910 // FIXME should descend into patterns to add defs.
911 sig
.text
.push_str(&pprust
::pat_to_string(&i
.pat
));
912 sig
.text
.push_str(": ");
913 let nested
= i
.ty
.make(sig
.text
.len(), Some(i
.id
), scx
)?
;
914 sig
.text
.push_str(&nested
.text
);
916 sig
.defs
.extend(nested
.defs
.into_iter());
917 sig
.refs
.extend(nested
.refs
.into_iter());
921 if let ast
::FnRetTy
::Ty(ref t
) = m
.decl
.output
{
922 sig
.text
.push_str(" -> ");
923 let nested
= t
.make(sig
.text
.len(), None
, scx
)?
;
924 sig
.text
.push_str(&nested
.text
);
925 sig
.defs
.extend(nested
.defs
.into_iter());
926 sig
.refs
.extend(nested
.refs
.into_iter());
928 sig
.text
.push_str(" {}");