extern crate ordermap; use ordermap::OrderMap; use std::fmt::{self, Write}; /// Defines a scope. /// /// A scope contains modules, types, etc... #[derive(Debug, Clone)] pub struct Scope { /// Scope documentation docs: Option, /// Imports imports: OrderMap>, /// Contents of the documentation, items: Vec, } #[derive(Debug, Clone)] enum Item { Module(Module), Struct(Struct), Enum(Enum), Impl(Impl), } /// Defines a module #[derive(Debug, Clone)] pub struct Module { /// Module name name: String, /// Visibility vis: Option, /// Module documentation docs: Option, /// Contents of the module scope: Scope, } /// Defines an enumeration #[derive(Debug, Clone)] pub struct Enum { type_def: TypeDef, variants: Vec, } /// Defines a struct #[derive(Debug, Clone)] pub struct Struct { type_def: TypeDef, /// Struct fields fields: Fields, } #[derive(Debug, Clone)] pub struct Type { name: String, generics: Vec, } /// A type definition #[derive(Debug, Clone)] struct TypeDef { ty: Type, vis: Option, docs: Option, derive: Vec, bounds: Vec, } /// An enum variant #[derive(Debug, Clone)] pub struct Variant { name: String, fields: Fields, } #[derive(Debug, Clone)] enum Fields { Empty, Tuple(Vec), Named(Vec), } /// Defines a struct field #[derive(Debug, Clone)] struct Field { /// Field name name: String, /// Field type ty: Type, } #[derive(Debug, Clone)] pub struct Impl { /// The struct being implemented target: Type, /// Impl level generics generics: Vec, /// If implementing a trait impl_trait: Option, /// Associated types assoc_tys: Vec, /// Bounds bounds: Vec, fns: Vec, } /// Import #[derive(Debug, Clone)] pub struct Import { line: String, vis: Option, } /// A function definition #[derive(Debug, Clone)] pub struct Function { /// Name of the function name: String, /// Function documentation docs: Option, /// Function visibility vis: Option, /// Function generics generics: Vec, /// If the function takes `&self` or `&mut self` arg_self: Option, /// Function arguments args: Vec, /// Return type ret: Option, /// Where bounds bounds: Vec, /// Body contents body: Vec, } /// A block of code #[derive(Debug, Clone)] pub struct Block { before: Option, after: Option, body: Vec, } #[derive(Debug, Clone)] enum Body { String(String), Block(Block), } #[derive(Debug, Clone)] struct Docs { docs: String, } /// Formatting configuration #[derive(Debug)] pub struct Formatter<'a> { /// Write destination dst: &'a mut String, /// Number of spaces to start a new line with spaces: usize, /// Number of spaces per indentiation indent: usize, } const DEFAULT_INDENT: usize = 4; // ===== impl Scope ===== impl Scope { /// Returns a new scope pub fn new() -> Self { Scope { docs: None, imports: OrderMap::new(), items: vec![], } } /// Push an `use` line pub fn import(&mut self, path: &str, ty: &str) -> &mut Import { self.imports.entry(path.to_string()) .or_insert(OrderMap::new()) .entry(ty.to_string()) .or_insert_with(|| Import::new(path, ty)) } /// Pushes a new module definition, returning a mutable reference to the /// definition. pub fn module(&mut self, name: &str) -> &mut Module { self.push_module(Module::new(name)); match *self.items.last_mut().unwrap() { Item::Module(ref mut v) => v, _ => unreachable!(), } } /// Push a module definition pub fn push_module(&mut self, module: Module) -> &mut Self { self.items.push(Item::Module(module)); self } /// Push a new struct definition, returning a mutable reference to the /// definition. pub fn structure(&mut self, name: &str) -> &mut Struct { self.push_structure(Struct::new(name)); match *self.items.last_mut().unwrap() { Item::Struct(ref mut v) => v, _ => unreachable!(), } } /// Push a structure definition pub fn push_structure(&mut self, structure: Struct) -> &mut Self { self.items.push(Item::Struct(structure)); self } /// Push a new struct definition, returning a mutable reference to the /// definition. pub fn enumeration(&mut self, name: &str) -> &mut Enum { self.push_enumeration(Enum::new(name)); match *self.items.last_mut().unwrap() { Item::Enum(ref mut v) => v, _ => unreachable!(), } } /// Push a structure definition pub fn push_enumeration(&mut self, enumeration: Enum) -> &mut Self { self.items.push(Item::Enum(enumeration)); self } pub fn imp(&mut self, target: &str) -> &mut Impl { self.push_imp(Impl::new(target)); match *self.items.last_mut().unwrap() { Item::Impl(ref mut v) => v, _ => unreachable!(), } } pub fn push_imp(&mut self, imp: Impl) -> &mut Self { self.items.push(Item::Impl(imp)); self } /// Return a string representation of the scope. pub fn to_string(&self) -> String { let mut ret = String::new(); self.fmt(&mut Formatter::new(&mut ret)).unwrap(); // Remove the trailing newline if ret.as_bytes().last() == Some(&b'\n') { ret.pop(); } ret } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.fmt_imports(fmt)?; if !self.imports.is_empty() { write!(fmt, "\n")?; } for (i, item) in self.items.iter().enumerate() { if i != 0 { write!(fmt, "\n")?; } match *item { Item::Module(ref v) => v.fmt(fmt)?, Item::Struct(ref v) => v.fmt(fmt)?, Item::Enum(ref v) => v.fmt(fmt)?, Item::Impl(ref v) => v.fmt(fmt)?, } } Ok(()) } fn fmt_imports(&self, fmt: &mut Formatter) -> fmt::Result { // First, collect all visibilities let mut visibilities = vec![]; for (_, imports) in &self.imports { for (_, import) in imports { if !visibilities.contains(&import.vis) { visibilities.push(import.vis.clone()); } } } let mut tys = vec![]; // Loop over all visibilities and format the associated imports for vis in &visibilities { for (path, imports) in &self.imports { tys.clear(); for (ty, import) in imports { if *vis == import.vis { tys.push(ty); } } if !tys.is_empty() { if let Some(ref vis) = *vis { write!(fmt, "{} ", vis)?; } write!(fmt, "use {}::", path)?; if tys.len() > 1 { write!(fmt, "{{")?; for (i, ty) in tys.iter().enumerate() { if i != 0 { write!(fmt, ", ")?; } write!(fmt, "{}", ty)?; } write!(fmt, "}};\n")?; } else if tys.len() == 1 { write!(fmt, "{};\n", tys[0])?; } } } } Ok(()) } } // ===== impl Module ===== impl Module { /// Return a new, blank module pub fn new(name: &str) -> Self { Module { name: name.to_string(), vis: None, docs: None, scope: Scope::new(), } } pub fn vis(&mut self, vis: &str) -> &mut Self { self.vis = Some(vis.to_string()); self } /// Push an `use` line pub fn import(&mut self, path: &str, ty: &str) -> &mut Self { self.scope.import(path, ty); self } /// Pushes a new module definition, returning a mutable reference to the /// definition. pub fn module(&mut self, name: &str) -> &mut Module { self.scope.module(name) } /// Push a module definition pub fn push_module(&mut self, module: Module) -> &mut Self { self.scope.push_module(module); self } /// Push a new struct definition, returning a mutable reference to the /// definition. pub fn structure(&mut self, name: &str) -> &mut Struct { self.scope.structure(name) } /// Push a structure definition pub fn push_structure(&mut self, structure: Struct) -> &mut Self { self.scope.push_structure(structure); self } /// Push a new struct definition, returning a mutable reference to the /// definition. pub fn enumeration(&mut self, name: &str) -> &mut Enum { self.scope.enumeration(name) } /// Push a structure definition pub fn push_enumeration(&mut self, enumeration: Enum) -> &mut Self { self.scope.push_enumeration(enumeration); self } pub fn imp(&mut self, target: &str) -> &mut Impl { self.scope.imp(target) } pub fn push_imp(&mut self, imp: Impl) -> &mut Self { self.scope.push_imp(imp); self } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { if let Some(ref vis) = self.vis { write!(fmt, "{} ", vis)?; } write!(fmt, "mod {}", self.name)?; fmt.block(|fmt| { self.scope.fmt(fmt) }) } } // ===== impl Struct ===== impl Struct { /// Return a structure definition with the provided name pub fn new(name: &str) -> Self { Struct { type_def: TypeDef::new(name), fields: Fields::Empty, } } /// Returns a reference to the type pub fn ty(&self) -> &Type { &self.type_def.ty } pub fn vis(&mut self, vis: &str) -> &mut Self { self.type_def.vis(vis); self } pub fn generic(&mut self, name: &str) -> &mut Self { self.type_def.ty.generic(name); self } pub fn bound(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.type_def.bound(name, ty); self } pub fn doc(&mut self, docs: &str) -> &mut Self { self.type_def.doc(docs); self } pub fn derive(&mut self, name: &str) -> &mut Self { self.type_def.derive(name); self } pub fn field(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.fields.named(name, ty); self } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.type_def.fmt_head("struct", fmt)?; self.fields.fmt(fmt)?; Ok(()) } } // ===== impl Enum ===== impl Enum { /// Return a structure definition with the provided name pub fn new(name: &str) -> Self { Enum { type_def: TypeDef::new(name), variants: vec![], } } /// Returns a reference to the type pub fn ty(&self) -> &Type { &self.type_def.ty } pub fn vis(&mut self, vis: &str) -> &mut Self { self.type_def.vis(vis); self } pub fn generic(&mut self, name: &str) -> &mut Self { self.type_def.ty.generic(name); self } pub fn bound(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.type_def.bound(name, ty); self } pub fn doc(&mut self, docs: &str) -> &mut Self { self.type_def.doc(docs); self } pub fn derive(&mut self, name: &str) -> &mut Self { self.type_def.derive(name); self } pub fn variant(&mut self, name: &str) -> &mut Variant { self.push_variant(Variant::new(name)); self.variants.last_mut().unwrap() } pub fn push_variant(&mut self, variant: Variant) -> &mut Self { self.variants.push(variant); self } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { self.type_def.fmt_head("enum", fmt)?; fmt.block(|fmt| { for variant in &self.variants { variant.fmt(fmt)?; } Ok(()) }) } } // ===== impl Variant ===== impl Variant { pub fn new(name: &str) -> Self { Variant { name: name.to_string(), fields: Fields::Empty, } } pub fn named(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.fields.named(name, ty); self } pub fn tuple(&mut self, ty: &str) -> &mut Self { self.fields.tuple(ty); self } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "{}", self.name)?; self.fields.fmt(fmt)?; write!(fmt, ",\n")?; Ok(()) } } // ===== impl Type ===== impl Type { pub fn new(name: &str) -> Self { Type { name: name.to_string(), generics: vec![], } } pub fn generic(&mut self, ty: T) -> &mut Self where T: Into, { // Make sure that the name doesn't already include generics assert!(!self.name.contains("<"), "type name already includes generics"); self.generics.push(ty.into()); self } /// Rewrite the `Type` with the provided path pub fn path(&self, path: &str) -> Type { // TODO: This isn't really correct assert!(!self.name.contains("::")); let mut name = path.to_string(); name.push_str("::"); name.push_str(&self.name); Type { name, generics: self.generics.clone(), } } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "{}", self.name)?; Type::fmt_slice(&self.generics, fmt) } fn fmt_slice(generics: &[Type], fmt: &mut Formatter) -> fmt::Result { if !generics.is_empty() { write!(fmt, "<")?; for (i, ty) in generics.iter().enumerate() { if i != 0 { write!(fmt, ", ")? } ty.fmt(fmt)?; } write!(fmt, ">")?; } Ok(()) } } impl<'a> From<&'a str> for Type { fn from(src: &'a str) -> Self { Type::new(src) } } impl From for Type { fn from(src: String) -> Self { Type { name: src, generics: vec![], } } } impl<'a> From<&'a String> for Type { fn from(src: &'a String) -> Self { Type::new(src) } } impl<'a> From<&'a Type> for Type { fn from(src: &'a Type) -> Self { src.clone() } } // ===== impl TypeDef ===== impl TypeDef { /// Return a structure definition with the provided name pub fn new(name: &str) -> Self { TypeDef { ty: Type::new(name), vis: None, docs: None, derive: vec![], bounds: vec![], } } fn vis(&mut self, vis: &str) { self.vis = Some(vis.to_string()); } fn bound(&mut self, name: &str, ty: T) where T: Into, { self.bounds.push(Field { name: name.to_string(), ty: ty.into(), }); } fn doc(&mut self, docs: &str) { self.docs = Some(Docs::new(docs)); } fn derive(&mut self, name: &str) { self.derive.push(name.to_string()); } fn fmt_head(&self, keyword: &str, fmt: &mut Formatter) -> fmt::Result { if let Some(ref docs) = self.docs { docs.fmt(fmt)?; } self.fmt_derive(fmt)?; if let Some(ref vis) = self.vis { write!(fmt, "{} ", vis)?; } write!(fmt, "{} ", keyword)?; self.ty.fmt(fmt)?; fmt_bounds(&self.bounds, fmt)?; Ok(()) } fn fmt_derive(&self, fmt: &mut Formatter) -> fmt::Result { if !self.derive.is_empty() { write!(fmt, "#[derive(")?; for (i, name) in self.derive.iter().enumerate() { if i != 0 { write!(fmt, ", ")? } write!(fmt, "{}", name)?; } write!(fmt, ")]\n")?; } Ok(()) } } fn fmt_generics(generics: &[String], fmt: &mut Formatter) -> fmt::Result { if !generics.is_empty() { write!(fmt, "<")?; for (i, ty) in generics.iter().enumerate() { if i != 0 { write!(fmt, ", ")? } write!(fmt, "{}", ty)?; } write!(fmt, ">")?; } Ok(()) } fn fmt_bounds(bounds: &[Field], fmt: &mut Formatter) -> fmt::Result { if !bounds.is_empty() { write!(fmt, "\n")?; // Write first bound write!(fmt, "where {}: ", bounds[0].name)?; bounds[0].ty.fmt(fmt)?; write!(fmt, ",\n")?; for bound in &bounds[1..] { write!(fmt, " {}: ", bound.name)?; bound.ty.fmt(fmt)?; write!(fmt, ",\n")?; } } Ok(()) } // ===== impl Fields ===== impl Fields { fn named(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { match *self { Fields::Empty => { *self = Fields::Named(vec![Field { name: name.to_string(), ty: ty.into(), }]); } Fields::Named(ref mut fields) => { fields.push(Field { name: name.to_string(), ty: ty.into(), }); } _ => panic!("field list is named"), } self } fn tuple(&mut self, ty: T) -> &mut Self where T: Into, { match *self { Fields::Empty => { *self = Fields::Tuple(vec![ty.into()]); } Fields::Tuple(ref mut fields) => { fields.push(ty.into()); } _ => panic!("field list is tuple"), } self } fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { match *self { Fields::Named(ref fields) => { assert!(!fields.is_empty()); fmt.block(|fmt| { for f in fields { write!(fmt, "{}: ", f.name)?; f.ty.fmt(fmt)?; write!(fmt, ",\n")?; } Ok(()) })?; } Fields::Tuple(ref tys) => { assert!(!tys.is_empty()); write!(fmt, "(")?; for (i, ty) in tys.iter().enumerate() { if i != 0 { write!(fmt, ", ")?; } ty.fmt(fmt)?; } write!(fmt, ")")?; } Fields::Empty => {} } Ok(()) } } // ===== impl Impl ===== impl Impl { /// Return a new impl definition pub fn new(target: T) -> Self where T: Into, { Impl { target: target.into(), generics: vec![], impl_trait: None, assoc_tys: vec![], bounds: vec![], fns: vec![], } } pub fn generic(&mut self, name: &str) -> &mut Self { self.generics.push(name.to_string()); self } pub fn target_generic(&mut self, ty: T) -> &mut Self where T: Into, { self.target.generic(ty); self } pub fn impl_trait(&mut self, name: &str) -> &mut Self { self.impl_trait = Some(name.to_string()); self } pub fn associate_type(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.assoc_tys.push(Field { name: name.to_string(), ty: ty.into(), }); self } pub fn bound(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.bounds.push(Field { name: name.to_string(), ty: ty.into(), }); self } /// Define a new function pub fn function(&mut self, name: &str) -> &mut Function { self.push_function(Function::new(name)); self.fns.last_mut().unwrap() } /// Push a function definition pub fn push_function(&mut self, func: Function) -> &mut Self { self.fns.push(func); self } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { write!(fmt, "impl")?; fmt_generics(&self.generics[..], fmt)?; if let Some(ref t) = self.impl_trait { write!(fmt, " {} for", t)?; } write!(fmt, " ")?; self.target.fmt(fmt)?; fmt_bounds(&self.bounds, fmt)?; fmt.block(|fmt| { // format associated types if !self.assoc_tys.is_empty() { for ty in &self.assoc_tys { write!(fmt, "type {} = ", ty.name)?; ty.ty.fmt(fmt)?; write!(fmt, ";\n")?; } } for (i, func) in self.fns.iter().enumerate() { if i != 0 || !self.assoc_tys.is_empty() { write!(fmt, "\n")?; } func.fmt(fmt)?; } Ok(()) }) } } // ===== impl Import ===== impl Import { pub fn new(path: &str, ty: &str) -> Self { Import { line: format!("{}::{}", path, ty), vis: None, } } pub fn vis(&mut self, vis: &str) -> &mut Self { self.vis = Some(vis.to_string()); self } } // ===== impl Func ===== impl Function { pub fn new(name: &str) -> Self { Function { name: name.to_string(), docs: None, vis: None, generics: vec![], arg_self: None, args: vec![], ret: None, bounds: vec![], body: vec![], } } pub fn docs(&mut self, docs: &str) -> &mut Self { self.docs = Some(Docs::new(docs)); self } pub fn vis(&mut self, vis: &str) -> &mut Self { self.vis = Some(vis.to_string()); self } pub fn generic(&mut self, name: &str) -> &mut Self { self.generics.push(name.to_string()); self } pub fn arg_self(&mut self) -> &mut Self { self.arg_self = Some("self".to_string()); self } pub fn arg_ref_self(&mut self) -> &mut Self { self.arg_self = Some("&self".to_string()); self } pub fn arg_mut_self(&mut self) -> &mut Self { self.arg_self = Some("&mut self".to_string()); self } pub fn arg(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.args.push(Field { name: name.to_string(), ty: ty.into(), }); self } pub fn ret(&mut self, ty: T) -> &mut Self where T: Into, { self.ret = Some(ty.into()); self } pub fn bound(&mut self, name: &str, ty: T) -> &mut Self where T: Into, { self.bounds.push(Field { name: name.to_string(), ty: ty.into(), }); self } pub fn line(&mut self, line: T) -> &mut Self where T: ToString, { self.body.push(Body::String(line.to_string())); self } pub fn block(&mut self, block: Block) -> &mut Self { self.body.push(Body::Block(block)); self } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { if let Some(ref docs) = self.docs { docs.fmt(fmt)?; } if let Some(ref vis) = self.vis { write!(fmt, "{} ", vis)?; } write!(fmt, "fn {}", self.name)?; fmt_generics(&self.generics, fmt)?; write!(fmt, "(")?; if let Some(ref s) = self.arg_self { write!(fmt, "{}", s)?; } for (i, arg) in self.args.iter().enumerate() { if i != 0 || self.arg_self.is_some() { write!(fmt, ", ")?; } write!(fmt, "{}: ", arg.name)?; arg.ty.fmt(fmt)?; } write!(fmt, ")")?; if let Some(ref ret) = self.ret { write!(fmt, " -> ")?; ret.fmt(fmt)?; } fmt_bounds(&self.bounds, fmt)?; fmt.block(|fmt| { for b in &self.body { b.fmt(fmt)?; } Ok(()) }) } } // ===== impl Block ===== impl Block { pub fn new(before: &str) -> Self { Block { before: Some(before.to_string()), after: None, body: vec![], } } pub fn line(&mut self, line: T) -> &mut Self where T: ToString, { self.body.push(Body::String(line.to_string())); self } pub fn block(&mut self, block: Block) -> &mut Self { self.body.push(Body::Block(block)); self } pub fn after(&mut self, after: &str) -> &mut Self { self.after = Some(after.to_string()); self } pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { if let Some(ref before) = self.before { write!(fmt, "{}", before)?; } // Inlined `Formatter::fmt` if !fmt.is_start_of_line() { write!(fmt, " ")?; } write!(fmt, "{{\n")?; fmt.indent(|fmt| { for b in &self.body { b.fmt(fmt)?; } Ok(()) })?; write!(fmt, "}}")?; if let Some(ref after) = self.after { write!(fmt, "{}", after)?; } write!(fmt, "\n")?; Ok(()) } } // ===== impl Body ===== impl Body { pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { match *self { Body::String(ref s) => { write!(fmt, "{}\n", s) } Body::Block(ref b) => { b.fmt(fmt) } } } } // ===== impl Docs ===== impl Docs { fn new(docs: &str) -> Self { Docs { docs: docs.to_string() } } fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { for line in self.docs.lines() { write!(fmt, "/// {}\n", line)?; } Ok(()) } } // ===== impl Formatter ===== impl<'a> Formatter<'a> { pub fn new(dst: &'a mut String) -> Self { Formatter { dst, spaces: 0, indent: DEFAULT_INDENT, } } fn block(&mut self, f: F) -> fmt::Result where F: FnOnce(&mut Self) -> fmt::Result { if !self.is_start_of_line() { write!(self, " ")?; } write!(self, "{{\n")?; self.indent(f)?; write!(self, "}}\n")?; Ok(()) } /// Call the given function with the indentation level incremented by one. fn indent(&mut self, f: F) -> R where F: FnOnce(&mut Self) -> R { self.spaces += self.indent; let ret = f(self); self.spaces -= self.indent; ret } fn is_start_of_line(&self) -> bool { self.dst.is_empty() || self.dst.as_bytes().last() == Some(&b'\n') } fn push_spaces(&mut self) { for _ in 0..self.spaces { self.dst.push_str(" "); } } } impl<'a> fmt::Write for Formatter<'a> { fn write_str(&mut self, s: &str) -> fmt::Result { let mut first = true; let mut should_indent = self.is_start_of_line(); for line in s.lines() { if !first { self.dst.push_str("\n"); } first = false; let do_indent = should_indent && !line.is_empty() && line.as_bytes()[0] != b'\n'; if do_indent { self.push_spaces(); } // If this loops again, then we just wrote a new line should_indent = true; self.dst.push_str(line); } if s.as_bytes().last() == Some(&b'\n') { self.dst.push_str("\n"); } Ok(()) } }