blob: 874455f4e61cbcd86635e7a870364e7b19688823 [file] [log] [blame]
David Tolnayb79ee962016-09-04 09:39:20 -07001use super::*;
2
David Tolnay771ecf42016-09-23 19:26:37 -07003/// An item
4///
5/// The name might be a dummy name in case of anonymous items
David Tolnayb79ee962016-09-04 09:39:20 -07006#[derive(Debug, Clone, Eq, PartialEq)]
7pub struct Item {
8 pub ident: Ident,
9 pub vis: Visibility,
10 pub attrs: Vec<Attribute>,
David Tolnayf38cdf62016-09-23 19:07:09 -070011 pub node: ItemKind,
David Tolnayb79ee962016-09-04 09:39:20 -070012}
13
14#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnayf38cdf62016-09-23 19:07:09 -070015pub enum ItemKind {
16 /// An`extern crate` item, with optional original crate name.
17 ///
18 /// E.g. `extern crate foo` or `extern crate foo_bar as foo`
19 ExternCrate(Option<Ident>),
20 /// A use declaration (`use` or `pub use`) item.
21 ///
22 /// E.g. `use foo;`, `use foo::bar;` or `use foo::bar as FooBar;`
23 Use(Box<ViewPath>),
24 /// A static item (`static` or `pub static`).
25 ///
26 /// E.g. `static FOO: i32 = 42;` or `static FOO: &'static str = "bar";`
27 Static(Box<Ty>, Mutability, Box<Expr>),
28 /// A constant item (`const` or `pub const`).
29 ///
30 /// E.g. `const FOO: i32 = 42;`
31 Const(Box<Ty>, Box<Expr>),
32 /// A function declaration (`fn` or `pub fn`).
33 ///
34 /// E.g. `fn foo(bar: usize) -> usize { .. }`
David Tolnay42602292016-10-01 22:25:45 -070035 Fn(Box<FnDecl>, Unsafety, Constness, Option<Abi>, Generics, Box<Block>),
David Tolnayf38cdf62016-09-23 19:07:09 -070036 /// A module declaration (`mod` or `pub mod`).
37 ///
38 /// E.g. `mod foo;` or `mod foo { .. }`
39 Mod(Vec<Item>),
40 /// An external module (`extern` or `pub extern`).
41 ///
42 /// E.g. `extern {}` or `extern "C" {}`
43 ForeignMod(ForeignMod),
44 /// A type alias (`type` or `pub type`).
45 ///
46 /// E.g. `type Foo = Bar<u8>;`
47 Ty(Box<Ty>, Generics),
48 /// An enum definition (`enum` or `pub enum`).
49 ///
50 /// E.g. `enum Foo<A, B> { C<A>, D<B> }`
51 Enum(Vec<Variant>, Generics),
52 /// A struct definition (`struct` or `pub struct`).
53 ///
54 /// E.g. `struct Foo<A> { x: A }`
55 Struct(VariantData, Generics),
56 /// A union definition (`union` or `pub union`).
57 ///
58 /// E.g. `union Foo<A, B> { x: A, y: B }`
59 Union(VariantData, Generics),
60 /// A Trait declaration (`trait` or `pub trait`).
61 ///
62 /// E.g. `trait Foo { .. }` or `trait Foo<T> { .. }`
63 Trait(Unsafety, Generics, Vec<TyParamBound>, Vec<TraitItem>),
64 // Default trait implementation.
65 ///
66 /// E.g. `impl Trait for .. {}` or `impl<T> Trait<T> for .. {}`
67 DefaultImpl(Unsafety, Path),
68 /// An implementation.
69 ///
70 /// E.g. `impl<A> Foo<A> { .. }` or `impl<A> Trait for Foo<A> { .. }`
71 Impl(Unsafety,
72 ImplPolarity,
73 Generics,
74 Option<Path>, // (optional) trait this impl implements
75 Box<Ty>, // self
76 Vec<ImplItem>),
77 /// A macro invocation (which includes macro definition).
78 ///
79 /// E.g. `macro_rules! foo { .. }` or `foo!(..)`
80 Mac(Mac),
David Tolnayb79ee962016-09-04 09:39:20 -070081}
82
83#[derive(Debug, Clone, Eq, PartialEq)]
David Tolnayf38cdf62016-09-23 19:07:09 -070084pub enum ViewPath {
85 /// `foo::bar::baz as quux`
86 ///
87 /// or just
88 ///
89 /// `foo::bar::baz` (with `as baz` implicitly on the right)
David Tolnayaed77b02016-09-23 20:50:31 -070090 Simple(Ident, Path),
David Tolnayf38cdf62016-09-23 19:07:09 -070091
92 /// `foo::bar::*`
David Tolnayaed77b02016-09-23 20:50:31 -070093 Glob(Path),
David Tolnayf38cdf62016-09-23 19:07:09 -070094
David Tolnayaed77b02016-09-23 20:50:31 -070095 /// `foo::bar::{a, b, c}`
96 List(Path, Vec<PathListItem>)
David Tolnayf38cdf62016-09-23 19:07:09 -070097}
98
99#[derive(Debug, Clone, Eq, PartialEq)]
100pub struct PathListItem {
101 pub name: Ident,
102 /// renamed in list, e.g. `use foo::{bar as baz};`
103 pub rename: Option<Ident>,
104}
105
106#[derive(Debug, Copy, Clone, Eq, PartialEq)]
107pub enum Unsafety {
108 Unsafe,
109 Normal,
110}
111
112#[derive(Debug, Copy, Clone, Eq, PartialEq)]
113pub enum Constness {
114 Const,
115 NotConst,
116}
117
118#[derive(Debug, Copy, Clone, Eq, PartialEq)]
119pub enum Defaultness {
120 Default,
121 Final,
122}
123
124#[derive(Debug, Clone, Eq, PartialEq)]
125pub struct Abi(pub String);
126
127/// Foreign module declaration.
128///
129/// E.g. `extern { .. }` or `extern C { .. }`
130#[derive(Debug, Clone, Eq, PartialEq)]
131pub struct ForeignMod {
132 pub abi: Abi,
133 pub items: Vec<ForeignItem>,
134}
135
136#[derive(Debug, Clone, Eq, PartialEq)]
137pub struct ForeignItem {
David Tolnayb79ee962016-09-04 09:39:20 -0700138 pub ident: Ident,
139 pub attrs: Vec<Attribute>,
David Tolnayf38cdf62016-09-23 19:07:09 -0700140 pub node: ForeignItemKind,
David Tolnayb79ee962016-09-04 09:39:20 -0700141 pub vis: Visibility,
David Tolnayf38cdf62016-09-23 19:07:09 -0700142}
143
David Tolnay771ecf42016-09-23 19:26:37 -0700144/// An item within an `extern` block
David Tolnayf38cdf62016-09-23 19:07:09 -0700145#[derive(Debug, Clone, Eq, PartialEq)]
146pub enum ForeignItemKind {
147 /// A foreign function
148 Fn(Box<FnDecl>, Generics),
149 /// A foreign static item (`static ext: u8`), with optional mutability
150 /// (the boolean is true when mutable)
151 Static(Box<Ty>, bool),
152}
153
154/// Represents an item declaration within a trait declaration,
155/// possibly including a default implementation. A trait item is
156/// either required (meaning it doesn't have an implementation, just a
157/// signature) or provided (meaning it has a default implementation).
158#[derive(Debug, Clone, Eq, PartialEq)]
159pub struct TraitItem {
160 pub ident: Ident,
David Tolnayb79ee962016-09-04 09:39:20 -0700161 pub attrs: Vec<Attribute>,
David Tolnayf38cdf62016-09-23 19:07:09 -0700162 pub node: TraitItemKind,
163}
164
165#[derive(Debug, Clone, Eq, PartialEq)]
166pub enum TraitItemKind {
167 Const(Ty, Option<Expr>),
168 Method(MethodSig, Option<Block>),
169 Type(Vec<TyParamBound>, Option<Ty>),
170 Macro(Mac),
David Tolnayb79ee962016-09-04 09:39:20 -0700171}
172
David Tolnay55337722016-09-11 12:58:56 -0700173#[derive(Debug, Copy, Clone, Eq, PartialEq)]
David Tolnayf38cdf62016-09-23 19:07:09 -0700174pub enum ImplPolarity {
175 /// `impl Trait for Type`
176 Positive,
177 /// `impl !Trait for Type`
178 Negative,
David Tolnay55337722016-09-11 12:58:56 -0700179}
180
David Tolnayf38cdf62016-09-23 19:07:09 -0700181#[derive(Debug, Clone, Eq, PartialEq)]
182pub struct ImplItem {
183 pub ident: Ident,
184 pub vis: Visibility,
185 pub defaultness: Defaultness,
186 pub attrs: Vec<Attribute>,
187 pub node: ImplItemKind,
David Tolnayf4bbbd92016-09-23 14:41:55 -0700188}
189
David Tolnayf38cdf62016-09-23 19:07:09 -0700190#[derive(Debug, Clone, Eq, PartialEq)]
191pub enum ImplItemKind {
192 Const(Ty, Expr),
193 Method(MethodSig, Block),
194 Type(Ty),
195 Macro(Mac),
David Tolnay9d8f1972016-09-04 11:58:48 -0700196}
David Tolnayd5025812016-09-04 14:21:46 -0700197
David Tolnayf38cdf62016-09-23 19:07:09 -0700198/// Represents a method's signature in a trait declaration,
199/// or in an implementation.
200#[derive(Debug, Clone, Eq, PartialEq)]
201pub struct MethodSig {
202 pub unsafety: Unsafety,
203 pub constness: Constness,
204 pub abi: Abi,
205 pub decl: FnDecl,
206 pub generics: Generics,
David Tolnayd5025812016-09-04 14:21:46 -0700207}
David Tolnayedf2b992016-09-23 20:43:45 -0700208
David Tolnay62f374c2016-10-02 13:37:00 -0700209/// Header (not the body) of a function declaration.
210///
211/// E.g. `fn foo(bar: baz)`
212#[derive(Debug, Clone, Eq, PartialEq)]
213pub struct FnDecl {
214 pub inputs: Vec<FnArg>,
215 pub output: FunctionRetTy,
216}
217
218/// An argument in a function header.
219///
220/// E.g. `bar: usize` as in `fn foo(bar: usize)`
221#[derive(Debug, Clone, Eq, PartialEq)]
222pub struct FnArg {
223 pub pat: Pat,
224 pub ty: Ty,
225}
226
David Tolnayedf2b992016-09-23 20:43:45 -0700227#[cfg(feature = "parsing")]
228pub mod parsing {
229 use super::*;
David Tolnay62f374c2016-10-02 13:37:00 -0700230 use {FunctionRetTy, Generics};
David Tolnay4a51dc72016-10-01 00:40:31 -0700231 use attr::parsing::outer_attr;
David Tolnayedf2b992016-09-23 20:43:45 -0700232 use data::parsing::visibility;
David Tolnay62f374c2016-10-02 13:37:00 -0700233 use expr::parsing::{block, expr, pat};
David Tolnay42602292016-10-01 22:25:45 -0700234 use generics::parsing::{generics, where_clause};
David Tolnayedf2b992016-09-23 20:43:45 -0700235 use ident::parsing::ident;
David Tolnay42602292016-10-01 22:25:45 -0700236 use lit::parsing::quoted_string;
David Tolnayedf2b992016-09-23 20:43:45 -0700237 use macro_input::{Body, MacroInput};
238 use macro_input::parsing::macro_input;
David Tolnay62f374c2016-10-02 13:37:00 -0700239 use ty::parsing::{mutability, ty};
David Tolnayedf2b992016-09-23 20:43:45 -0700240
241 named!(pub item -> Item, alt!(
David Tolnaya96a3fa2016-09-24 07:17:42 -0700242 item_extern_crate
243 // TODO: Use
David Tolnay47a877c2016-10-01 16:50:55 -0700244 |
245 item_static
246 |
247 item_const
David Tolnay42602292016-10-01 22:25:45 -0700248 |
249 item_fn
David Tolnaya96a3fa2016-09-24 07:17:42 -0700250 // TODO: Mod
251 // TODO: ForeignMod
David Tolnay3cf52982016-10-01 17:11:37 -0700252 |
253 item_ty
David Tolnayedf2b992016-09-23 20:43:45 -0700254 |
David Tolnaya96a3fa2016-09-24 07:17:42 -0700255 item_struct_or_enum
256 // TODO: Union
257 // TODO: Trait
258 // TODO: DefaultImpl
259 // TODO: Impl
260 // TODO: Mac
David Tolnayedf2b992016-09-23 20:43:45 -0700261 ));
262
David Tolnaya96a3fa2016-09-24 07:17:42 -0700263 named!(item_extern_crate -> Item, do_parse!(
David Tolnay4a51dc72016-10-01 00:40:31 -0700264 attrs: many0!(outer_attr) >>
David Tolnayedf2b992016-09-23 20:43:45 -0700265 vis: visibility >>
David Tolnay10413f02016-09-30 09:12:02 -0700266 keyword!("extern") >>
267 keyword!("crate") >>
David Tolnayedf2b992016-09-23 20:43:45 -0700268 id: ident >>
269 rename: option!(preceded!(
David Tolnay10413f02016-09-30 09:12:02 -0700270 keyword!("as"),
David Tolnayedf2b992016-09-23 20:43:45 -0700271 ident
272 )) >>
273 punct!(";") >>
274 ({
275 let (name, original_name) = match rename {
276 Some(rename) => (rename, Some(id)),
277 None => (id, None),
278 };
279 Item {
280 ident: name,
281 vis: vis,
282 attrs: attrs,
283 node: ItemKind::ExternCrate(original_name),
284 }
285 })
286 ));
287
David Tolnay47a877c2016-10-01 16:50:55 -0700288 named!(item_static -> Item, do_parse!(
289 attrs: many0!(outer_attr) >>
290 vis: visibility >>
291 keyword!("static") >>
292 mutability: mutability >>
293 id: ident >>
294 punct!(":") >>
295 ty: ty >>
296 punct!("=") >>
297 value: expr >>
298 punct!(";") >>
299 (Item {
300 ident: id,
301 vis: vis,
302 attrs: attrs,
303 node: ItemKind::Static(Box::new(ty), mutability, Box::new(value)),
304 })
305 ));
306
307 named!(item_const -> Item, do_parse!(
308 attrs: many0!(outer_attr) >>
309 vis: visibility >>
310 keyword!("const") >>
311 id: ident >>
312 punct!(":") >>
313 ty: ty >>
314 punct!("=") >>
315 value: expr >>
316 punct!(";") >>
317 (Item {
318 ident: id,
319 vis: vis,
320 attrs: attrs,
321 node: ItemKind::Const(Box::new(ty), Box::new(value)),
322 })
323 ));
324
David Tolnay42602292016-10-01 22:25:45 -0700325 named!(item_fn -> Item, do_parse!(
326 attrs: many0!(outer_attr) >>
327 vis: visibility >>
328 constness: constness >>
329 unsafety: unsafety >>
330 abi: option!(preceded!(keyword!("extern"), quoted_string)) >>
331 keyword!("fn") >>
332 name: ident >>
333 generics: generics >>
334 punct!("(") >>
335 inputs: separated_list!(punct!(","), fn_arg) >>
336 punct!(")") >>
337 ret: option!(preceded!(punct!("->"), ty)) >>
338 where_clause: where_clause >>
339 body: block >>
340 (Item {
341 ident: name,
342 vis: vis,
343 attrs: attrs,
344 node: ItemKind::Fn(
345 Box::new(FnDecl {
346 inputs: inputs,
347 output: ret.map(FunctionRetTy::Ty).unwrap_or(FunctionRetTy::Default),
348 }),
349 unsafety,
350 constness,
351 abi.map(Abi),
352 Generics {
353 where_clause: where_clause,
354 .. generics
355 },
356 Box::new(body),
357 ),
358 })
359 ));
360
David Tolnay62f374c2016-10-02 13:37:00 -0700361 named!(fn_arg -> FnArg, do_parse!(
362 pat: pat >>
363 punct!(":") >>
364 ty: ty >>
365 (FnArg {
366 pat: pat,
367 ty: ty,
368 })
369 ));
370
David Tolnay3cf52982016-10-01 17:11:37 -0700371 named!(item_ty -> Item, do_parse!(
372 attrs: many0!(outer_attr) >>
373 vis: visibility >>
374 keyword!("type") >>
375 id: ident >>
376 generics: generics >>
377 punct!("=") >>
378 ty: ty >>
379 punct!(";") >>
380 (Item {
381 ident: id,
382 vis: vis,
383 attrs: attrs,
384 node: ItemKind::Ty(Box::new(ty), generics),
385 })
386 ));
387
David Tolnaya96a3fa2016-09-24 07:17:42 -0700388 named!(item_struct_or_enum -> Item, map!(
David Tolnayedf2b992016-09-23 20:43:45 -0700389 macro_input,
390 |def: MacroInput| Item {
391 ident: def.ident,
392 vis: def.vis,
393 attrs: def.attrs,
394 node: match def.body {
395 Body::Enum(variants) => {
396 ItemKind::Enum(variants, def.generics)
397 }
398 Body::Struct(variant_data) => {
399 ItemKind::Struct(variant_data, def.generics)
400 }
401 }
402 }
403 ));
David Tolnay42602292016-10-01 22:25:45 -0700404
405 named!(constness -> Constness, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700406 keyword!("const") => { |_| Constness::Const }
David Tolnay42602292016-10-01 22:25:45 -0700407 |
408 epsilon!() => { |_| Constness::NotConst }
409 ));
410
411 named!(unsafety -> Unsafety, alt!(
David Tolnaybd76e572016-10-02 13:43:16 -0700412 keyword!("unsafe") => { |_| Unsafety::Unsafe }
David Tolnay42602292016-10-01 22:25:45 -0700413 |
414 epsilon!() => { |_| Unsafety::Normal }
415 ));
David Tolnayedf2b992016-09-23 20:43:45 -0700416}
David Tolnay4a51dc72016-10-01 00:40:31 -0700417
418#[cfg(feature = "printing")]
419mod printing {
420 use super::*;
David Tolnay62f374c2016-10-02 13:37:00 -0700421 use FunctionRetTy;
David Tolnay4a51dc72016-10-01 00:40:31 -0700422 use attr::FilterAttrs;
David Tolnay47a877c2016-10-01 16:50:55 -0700423 use data::VariantData;
David Tolnay4a51dc72016-10-01 00:40:31 -0700424 use quote::{Tokens, ToTokens};
425
426 impl ToTokens for Item {
427 fn to_tokens(&self, tokens: &mut Tokens) {
428 for attr in self.attrs.outer() {
429 attr.to_tokens(tokens);
430 }
431 match self.node {
432 ItemKind::ExternCrate(ref original) => {
433 tokens.append("extern");
434 tokens.append("crate");
435 if let Some(ref original) = *original {
436 original.to_tokens(tokens);
437 tokens.append("as");
438 }
439 self.ident.to_tokens(tokens);
440 tokens.append(";");
441 }
442 ItemKind::Use(ref _view_path) => unimplemented!(),
David Tolnay47a877c2016-10-01 16:50:55 -0700443 ItemKind::Static(ref ty, ref mutability, ref expr) => {
444 self.vis.to_tokens(tokens);
445 tokens.append("static");
446 mutability.to_tokens(tokens);
447 self.ident.to_tokens(tokens);
448 tokens.append(":");
449 ty.to_tokens(tokens);
450 tokens.append("=");
451 expr.to_tokens(tokens);
452 tokens.append(";");
453 }
454 ItemKind::Const(ref ty, ref expr) => {
455 self.vis.to_tokens(tokens);
456 tokens.append("const");
457 self.ident.to_tokens(tokens);
458 tokens.append(":");
459 ty.to_tokens(tokens);
460 tokens.append("=");
461 expr.to_tokens(tokens);
462 tokens.append(";");
463 }
David Tolnay42602292016-10-01 22:25:45 -0700464 ItemKind::Fn(ref decl, unsafety, constness, ref abi, ref generics, ref block) => {
465 self.vis.to_tokens(tokens);
466 constness.to_tokens(tokens);
467 unsafety.to_tokens(tokens);
468 abi.to_tokens(tokens);
469 tokens.append("fn");
470 self.ident.to_tokens(tokens);
471 generics.to_tokens(tokens);
David Tolnay62f374c2016-10-02 13:37:00 -0700472 tokens.append("(");
473 tokens.append_separated(&decl.inputs, ",");
474 tokens.append(")");
475 if let FunctionRetTy::Ty(ref ty) = decl.output {
476 tokens.append("->");
477 ty.to_tokens(tokens);
478 }
David Tolnay42602292016-10-01 22:25:45 -0700479 generics.where_clause.to_tokens(tokens);
480 block.to_tokens(tokens);
481 }
David Tolnay4a51dc72016-10-01 00:40:31 -0700482 ItemKind::Mod(ref _items) => unimplemented!(),
483 ItemKind::ForeignMod(ref _foreign_mod) => unimplemented!(),
David Tolnay3cf52982016-10-01 17:11:37 -0700484 ItemKind::Ty(ref ty, ref generics) => {
485 self.vis.to_tokens(tokens);
486 tokens.append("type");
487 self.ident.to_tokens(tokens);
488 generics.to_tokens(tokens);
489 tokens.append("=");
490 ty.to_tokens(tokens);
491 tokens.append(";");
492 }
David Tolnay4a51dc72016-10-01 00:40:31 -0700493 ItemKind::Enum(ref variants, ref generics) => {
David Tolnay47a877c2016-10-01 16:50:55 -0700494 self.vis.to_tokens(tokens);
David Tolnay4a51dc72016-10-01 00:40:31 -0700495 tokens.append("enum");
496 self.ident.to_tokens(tokens);
497 generics.to_tokens(tokens);
498 generics.where_clause.to_tokens(tokens);
499 tokens.append("{");
500 for variant in variants {
501 variant.to_tokens(tokens);
502 tokens.append(",");
503 }
504 tokens.append("}");
505 }
506 ItemKind::Struct(ref variant_data, ref generics) => {
David Tolnay47a877c2016-10-01 16:50:55 -0700507 self.vis.to_tokens(tokens);
David Tolnay4a51dc72016-10-01 00:40:31 -0700508 tokens.append("struct");
509 self.ident.to_tokens(tokens);
510 generics.to_tokens(tokens);
511 generics.where_clause.to_tokens(tokens);
512 variant_data.to_tokens(tokens);
513 match *variant_data {
514 VariantData::Struct(_) => { /* no semicolon */ }
515 VariantData::Tuple(_) |
516 VariantData::Unit => tokens.append(";"),
517 }
518 }
519 ItemKind::Union(ref _variant_data, ref _generics) => unimplemented!(),
520 ItemKind::Trait(_unsafety, ref _generics, ref _bound, ref _item) => unimplemented!(),
521 ItemKind::DefaultImpl(_unsafety, ref _path) => unimplemented!(),
522 ItemKind::Impl(_unsafety, _polarity, ref _generics, ref _path, ref _ty, ref _item) => unimplemented!(),
523 ItemKind::Mac(ref _mac) => unimplemented!(),
524 }
525 }
526 }
David Tolnay42602292016-10-01 22:25:45 -0700527
David Tolnay62f374c2016-10-02 13:37:00 -0700528 impl ToTokens for FnArg {
529 fn to_tokens(&self, tokens: &mut Tokens) {
530 self.pat.to_tokens(tokens);
531 tokens.append(":");
532 self.ty.to_tokens(tokens);
533 }
534 }
535
David Tolnay42602292016-10-01 22:25:45 -0700536 impl ToTokens for Unsafety {
537 fn to_tokens(&self, tokens: &mut Tokens) {
538 match *self {
539 Unsafety::Unsafe => tokens.append("unsafe"),
540 Unsafety::Normal => { /* nothing */ },
541 }
542 }
543 }
544
545 impl ToTokens for Constness {
546 fn to_tokens(&self, tokens: &mut Tokens) {
547 match *self {
548 Constness::Const => tokens.append("const"),
549 Constness::NotConst => { /* nothing */ },
550 }
551 }
552 }
553
554 impl ToTokens for Abi {
555 fn to_tokens(&self, tokens: &mut Tokens) {
556 tokens.append("extern");
557 self.0.to_tokens(tokens);
558 }
559 }
David Tolnay4a51dc72016-10-01 00:40:31 -0700560}