#![deny(warnings, missing_debug_implementations, missing_docs)]
#![doc(html_root_url = "https://docs.rs/codegen/0.1.1")]
extern crate indexmap;
use indexmap::IndexMap;
use std::fmt::{self, Write};
#[derive(Debug, Clone)]
pub struct Scope {
docs: Option<Docs>,
imports: IndexMap<String, IndexMap<String, Import>>,
items: Vec<Item>,
}
#[derive(Debug, Clone)]
enum Item {
Module(Module),
Struct(Struct),
Function(Function),
Trait(Trait),
Enum(Enum),
Impl(Impl),
Raw(String),
}
#[derive(Debug, Clone)]
pub struct Module {
name: String,
vis: Option<String>,
docs: Option<Docs>,
scope: Scope,
}
#[derive(Debug, Clone)]
pub struct Enum {
type_def: TypeDef,
variants: Vec<Variant>,
}
#[derive(Debug, Clone)]
pub struct Struct {
type_def: TypeDef,
fields: Fields,
}
#[derive(Debug, Clone)]
pub struct Trait {
type_def: TypeDef,
parents: Vec<Type>,
associated_tys: Vec<AssociatedType>,
fns: Vec<Function>,
}
#[derive(Debug, Clone)]
pub struct Type {
name: String,
generics: Vec<Type>,
}
#[derive(Debug, Clone)]
struct TypeDef {
ty: Type,
vis: Option<String>,
docs: Option<Docs>,
derive: Vec<String>,
allow: Option<String>,
repr: Option<String>,
bounds: Vec<Bound>,
}
#[derive(Debug, Clone)]
pub struct Variant {
name: String,
fields: Fields,
}
#[derive(Debug, Clone)]
enum Fields {
Empty,
Tuple(Vec<Type>),
Named(Vec<Field>),
}
#[derive(Debug, Clone)]
pub struct Field {
name: String,
ty: Type,
documentation: Vec<String>,
annotation: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct AssociatedType(Bound);
#[derive(Debug, Clone)]
struct Bound {
name: String,
bound: Vec<Type>,
}
#[derive(Debug, Clone)]
pub struct Impl {
target: Type,
generics: Vec<String>,
impl_trait: Option<Type>,
assoc_tys: Vec<Field>,
bounds: Vec<Bound>,
fns: Vec<Function>,
}
#[derive(Debug, Clone)]
pub struct Import {
line: String,
vis: Option<String>,
}
#[derive(Debug, Clone)]
pub struct Function {
name: String,
docs: Option<Docs>,
allow: Option<String>,
vis: Option<String>,
generics: Vec<String>,
arg_self: Option<String>,
args: Vec<Field>,
ret: Option<Type>,
bounds: Vec<Bound>,
body: Option<Vec<Body>>,
}
#[derive(Debug, Clone)]
pub struct Block {
before: Option<String>,
after: Option<String>,
body: Vec<Body>,
}
#[derive(Debug, Clone)]
enum Body {
String(String),
Block(Block),
}
#[derive(Debug, Clone)]
struct Docs {
docs: String,
}
#[derive(Debug)]
pub struct Formatter<'a> {
dst: &'a mut String,
spaces: usize,
indent: usize,
}
const DEFAULT_INDENT: usize = 4;
impl Scope {
pub fn new() -> Self {
Scope {
docs: None,
imports: IndexMap::new(),
items: vec![],
}
}
pub fn import(&mut self, path: &str, ty: &str) -> &mut Import {
let ty = ty.split("::").next().unwrap_or(ty);
self.imports.entry(path.to_string())
.or_insert(IndexMap::new())
.entry(ty.to_string())
.or_insert_with(|| Import::new(path, ty))
}
pub fn new_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!(),
}
}
pub fn get_module_mut<Q: ?Sized>(&mut self,
name: &Q)
-> Option<&mut Module>
where
String: PartialEq<Q>,
{
self.items.iter_mut()
.filter_map(|item| match item {
&mut Item::Module(ref mut module) if module.name == *name =>
Some(module),
_ => None,
})
.next()
}
pub fn get_module<Q: ?Sized>(&self, name: &Q) -> Option<&Module>
where
String: PartialEq<Q>,
{
self.items.iter()
.filter_map(|item| match item {
&Item::Module(ref module) if module.name == *name =>
Some(module),
_ => None,
})
.next()
}
pub fn get_or_new_module(&mut self, name: &str) -> &mut Module {
if self.get_module(name).is_some() {
self.get_module_mut(name).unwrap()
} else {
self.new_module(name)
}
}
pub fn push_module(&mut self, item: Module) -> &mut Self {
assert!(self.get_module(&item.name).is_none());
self.items.push(Item::Module(item));
self
}
pub fn new_struct(&mut self, name: &str) -> &mut Struct {
self.push_struct(Struct::new(name));
match *self.items.last_mut().unwrap() {
Item::Struct(ref mut v) => v,
_ => unreachable!(),
}
}
pub fn push_struct(&mut self, item: Struct) -> &mut Self {
self.items.push(Item::Struct(item));
self
}
pub fn new_fn(&mut self, name: &str) -> &mut Function {
self.push_fn(Function::new(name));
match *self.items.last_mut().unwrap() {
Item::Function(ref mut v) => v,
_ => unreachable!(),
}
}
pub fn push_fn(&mut self, item: Function) -> &mut Self {
self.items.push(Item::Function(item));
self
}
pub fn new_trait(&mut self, name: &str) -> &mut Trait {
self.push_trait(Trait::new(name));
match *self.items.last_mut().unwrap() {
Item::Trait(ref mut v) => v,
_ => unreachable!(),
}
}
pub fn push_trait(&mut self, item: Trait) -> &mut Self {
self.items.push(Item::Trait(item));
self
}
pub fn new_enum(&mut self, name: &str) -> &mut Enum {
self.push_enum(Enum::new(name));
match *self.items.last_mut().unwrap() {
Item::Enum(ref mut v) => v,
_ => unreachable!(),
}
}
pub fn push_enum(&mut self, item: Enum) -> &mut Self {
self.items.push(Item::Enum(item));
self
}
pub fn new_impl(&mut self, target: &str) -> &mut Impl {
self.push_impl(Impl::new(target));
match *self.items.last_mut().unwrap() {
Item::Impl(ref mut v) => v,
_ => unreachable!(),
}
}
pub fn push_impl(&mut self, item: Impl) -> &mut Self {
self.items.push(Item::Impl(item));
self
}
pub fn raw(&mut self, val: &str) -> &mut Self {
self.items.push(Item::Raw(val.to_string()));
self
}
pub fn to_string(&self) -> String {
let mut ret = String::new();
self.fmt(&mut Formatter::new(&mut ret)).unwrap();
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::Function(ref v) => v.fmt(false, fmt)?,
Item::Trait(ref v) => v.fmt(fmt)?,
Item::Enum(ref v) => v.fmt(fmt)?,
Item::Impl(ref v) => v.fmt(fmt)?,
Item::Raw(ref v) => {
write!(fmt, "{}\n", v)?;
}
}
}
Ok(())
}
fn fmt_imports(&self, fmt: &mut Formatter) -> fmt::Result {
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![];
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 {
pub fn new(name: &str) -> Self {
Module {
name: name.to_string(),
vis: None,
docs: None,
scope: Scope::new(),
}
}
pub fn scope(&mut self) -> &mut Scope {
&mut self.scope
}
pub fn vis(&mut self, vis: &str) -> &mut Self {
self.vis = Some(vis.to_string());
self
}
pub fn import(&mut self, path: &str, ty: &str) -> &mut Self {
self.scope.import(path, ty);
self
}
pub fn new_module(&mut self, name: &str) -> &mut Module {
self.scope.new_module(name)
}
pub fn get_module<Q: ?Sized>(&self, name: &Q) -> Option<&Module>
where
String: PartialEq<Q>,
{
self.scope.get_module(name)
}
pub fn get_module_mut<Q: ?Sized>(&mut self,
name: &Q)
-> Option<&mut Module>
where
String: PartialEq<Q>,
{
self.scope.get_module_mut(name)
}
pub fn get_or_new_module(&mut self, name: &str) -> &mut Module {
self.scope.get_or_new_module(name)
}
pub fn push_module(&mut self, item: Module) -> &mut Self {
self.scope.push_module(item);
self
}
pub fn new_struct(&mut self, name: &str) -> &mut Struct {
self.scope.new_struct(name)
}
pub fn push_struct(&mut self, item: Struct) -> &mut Self {
self.scope.push_struct(item);
self
}
pub fn new_fn(&mut self, name: &str) -> &mut Function {
self.scope.new_fn(name)
}
pub fn push_fn(&mut self, item: Function) -> &mut Self {
self.scope.push_fn(item);
self
}
pub fn new_enum(&mut self, name: &str) -> &mut Enum {
self.scope.new_enum(name)
}
pub fn push_enum(&mut self, item: Enum) -> &mut Self {
self.scope.push_enum(item);
self
}
pub fn new_impl(&mut self, target: &str) -> &mut Impl {
self.scope.new_impl(target)
}
pub fn push_impl(&mut self, item: Impl) -> &mut Self {
self.scope.push_impl(item);
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 {
pub fn new(name: &str) -> Self {
Struct {
type_def: TypeDef::new(name),
fields: Fields::Empty,
}
}
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<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
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 allow(&mut self, allow: &str) -> &mut Self {
self.type_def.allow(allow);
self
}
pub fn repr(&mut self, repr: &str) -> &mut Self {
self.type_def.repr(repr);
self
}
pub fn push_field(&mut self, field: Field) -> &mut Self
{
self.fields.push_named(field);
self
}
pub fn field<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.fields.named(name, ty);
self
}
pub fn tuple_field<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.fields.tuple(ty);
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.type_def.fmt_head("struct", &[], fmt)?;
self.fields.fmt(fmt)?;
match self.fields {
Fields::Empty => {
write!(fmt, ";\n")?;
}
Fields::Tuple(..) => {
write!(fmt, ";\n")?;
}
_ => {}
}
Ok(())
}
}
impl Trait {
pub fn new(name: &str) -> Self {
Trait {
type_def: TypeDef::new(name),
parents: vec![],
associated_tys: vec![],
fns: vec![],
}
}
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<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.type_def.bound(name, ty);
self
}
pub fn parent<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.parents.push(ty.into());
self
}
pub fn doc(&mut self, docs: &str) -> &mut Self {
self.type_def.doc(docs);
self
}
pub fn associated_type(&mut self, name: &str) -> &mut AssociatedType {
self.associated_tys.push(AssociatedType(Bound {
name: name.to_string(),
bound: vec![],
}));
self.associated_tys.last_mut().unwrap()
}
pub fn new_fn(&mut self, name: &str) -> &mut Function {
let mut func = Function::new(name);
func.body = None;
self.push_fn(func);
self.fns.last_mut().unwrap()
}
pub fn push_fn(&mut self, item: Function) -> &mut Self {
self.fns.push(item);
self
}
pub fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
self.type_def.fmt_head("trait", &self.parents, fmt)?;
fmt.block(|fmt| {
let assoc = &self.associated_tys;
if !assoc.is_empty() {
for ty in assoc {
let ty = &ty.0;
write!(fmt, "type {}", ty.name)?;
if !ty.bound.is_empty() {
write!(fmt, ": ")?;
fmt_bound_rhs(&ty.bound, fmt)?;
}
write!(fmt, ";\n")?;
}
}
for (i, func) in self.fns.iter().enumerate() {
if i != 0 || !assoc.is_empty() { write!(fmt, "\n")?; }
func.fmt(true, fmt)?;
}
Ok(())
})
}
}
impl Enum {
pub fn new(name: &str) -> Self {
Enum {
type_def: TypeDef::new(name),
variants: vec![],
}
}
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<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
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 allow(&mut self, allow: &str) -> &mut Self {
self.type_def.allow(allow);
self
}
pub fn repr(&mut self, repr: &str) -> &mut Self {
self.type_def.repr(repr);
self
}
pub fn new_variant(&mut self, name: &str) -> &mut Variant {
self.push_variant(Variant::new(name));
self.variants.last_mut().unwrap()
}
pub fn push_variant(&mut self, item: Variant) -> &mut Self {
self.variants.push(item);
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 {
pub fn new(name: &str) -> Self {
Variant {
name: name.to_string(),
fields: Fields::Empty,
}
}
pub fn named<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
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 {
pub fn new(name: &str) -> Self {
Type {
name: name.to_string(),
generics: vec![],
}
}
pub fn generic<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
assert!(!self.name.contains("<"), "type name already includes generics");
self.generics.push(ty.into());
self
}
pub fn path(&self, path: &str) -> Type {
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<String> 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 {
fn new(name: &str) -> Self {
TypeDef {
ty: Type::new(name),
vis: None,
docs: None,
derive: vec![],
allow: None,
repr: None,
bounds: vec![],
}
}
fn vis(&mut self, vis: &str) {
self.vis = Some(vis.to_string());
}
fn bound<T>(&mut self, name: &str, ty: T)
where T: Into<Type>,
{
self.bounds.push(Bound {
name: name.to_string(),
bound: vec![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 allow(&mut self, allow: &str) {
self.allow = Some(allow.to_string());
}
fn repr(&mut self, repr: &str) {
self.repr = Some(repr.to_string());
}
fn fmt_head(&self,
keyword: &str,
parents: &[Type],
fmt: &mut Formatter) -> fmt::Result
{
if let Some(ref docs) = self.docs {
docs.fmt(fmt)?;
}
self.fmt_allow(fmt)?;
self.fmt_derive(fmt)?;
self.fmt_repr(fmt)?;
if let Some(ref vis) = self.vis {
write!(fmt, "{} ", vis)?;
}
write!(fmt, "{} ", keyword)?;
self.ty.fmt(fmt)?;
if !parents.is_empty() {
for (i, ty) in parents.iter().enumerate() {
if i == 0 {
write!(fmt, ": ")?;
} else {
write!(fmt, " + ")?;
}
ty.fmt(fmt)?;
}
}
fmt_bounds(&self.bounds, fmt)?;
Ok(())
}
fn fmt_allow(&self, fmt: &mut Formatter) -> fmt::Result {
if let Some(ref allow) = self.allow {
write!(fmt, "#[allow({})]\n", allow)?;
}
Ok(())
}
fn fmt_repr(&self, fmt: &mut Formatter) -> fmt::Result {
if let Some(ref repr) = self.repr {
write!(fmt, "#[repr({})]\n", repr)?;
}
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: &[Bound], fmt: &mut Formatter) -> fmt::Result {
if !bounds.is_empty() {
write!(fmt, "\n")?;
write!(fmt, "where {}: ", bounds[0].name)?;
fmt_bound_rhs(&bounds[0].bound, fmt)?;
write!(fmt, ",\n")?;
for bound in &bounds[1..] {
write!(fmt, " {}: ", bound.name)?;
fmt_bound_rhs(&bound.bound, fmt)?;
write!(fmt, ",\n")?;
}
}
Ok(())
}
fn fmt_bound_rhs(tys: &[Type], fmt: &mut Formatter) -> fmt::Result {
for (i, ty) in tys.iter().enumerate() {
if i != 0 { write!(fmt, " + ")? }
ty.fmt(fmt)?;
}
Ok(())
}
impl AssociatedType {
pub fn bound<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.0.bound.push(ty.into());
self
}
}
impl Field {
pub fn new<T>(name: &str, ty: T) -> Self
where T: Into<Type>,
{
Field {
name: name.into(),
ty: ty.into(),
documentation: Vec::new(),
annotation: Vec::new(),
}
}
pub fn doc(&mut self, documentation: Vec<&str>) -> &mut Self {
self.documentation = documentation.iter().map(|doc| doc.to_string()).collect();
self
}
pub fn annotation(&mut self, annotation: Vec<&str>) -> &mut Self {
self.annotation = annotation.iter().map(|ann| ann.to_string()).collect();
self
}
}
impl Fields {
fn push_named(&mut self, field: Field) -> &mut Self
{
match *self {
Fields::Empty => {
*self = Fields::Named(vec![field]);
}
Fields::Named(ref mut fields) => {
fields.push(field);
}
_ => panic!("field list is named"),
}
self
}
fn named<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.push_named(Field {
name: name.to_string(),
ty: ty.into(),
documentation: Vec::new(),
annotation: Vec::new(),
})
}
fn tuple<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
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 {
if !f.documentation.is_empty() {
for doc in &f.documentation {
write!(fmt, "/// {}\n", doc)?;
}
}
if !f.annotation.is_empty() {
for ann in &f.annotation {
write!(fmt, "{}\n", ann)?;
}
}
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 {
pub fn new<T>(target: T) -> Self
where T: Into<Type>,
{
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<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.target.generic(ty);
self
}
pub fn impl_trait<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.impl_trait = Some(ty.into());
self
}
pub fn associate_type<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.assoc_tys.push(Field {
name: name.to_string(),
ty: ty.into(),
documentation: Vec::new(),
annotation: Vec::new(),
});
self
}
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.bounds.push(Bound {
name: name.to_string(),
bound: vec![ty.into()],
});
self
}
pub fn new_fn(&mut self, name: &str) -> &mut Function {
self.push_fn(Function::new(name));
self.fns.last_mut().unwrap()
}
pub fn push_fn(&mut self, item: Function) -> &mut Self {
self.fns.push(item);
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, " ")?;
t.fmt(fmt)?;
write!(fmt, " for")?;
}
write!(fmt, " ")?;
self.target.fmt(fmt)?;
fmt_bounds(&self.bounds, fmt)?;
fmt.block(|fmt| {
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(false, fmt)?;
}
Ok(())
})
}
}
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 Function {
pub fn new(name: &str) -> Self {
Function {
name: name.to_string(),
docs: None,
allow: None,
vis: None,
generics: vec![],
arg_self: None,
args: vec![],
ret: None,
bounds: vec![],
body: Some(vec![]),
}
}
pub fn doc(&mut self, docs: &str) -> &mut Self {
self.docs = Some(Docs::new(docs));
self
}
pub fn allow(&mut self, allow: &str) -> &mut Self {
self.allow = Some(allow.to_string());
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<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.args.push(Field {
name: name.to_string(),
ty: ty.into(),
documentation: Vec::new(),
annotation: Vec::new(),
});
self
}
pub fn ret<T>(&mut self, ty: T) -> &mut Self
where T: Into<Type>,
{
self.ret = Some(ty.into());
self
}
pub fn bound<T>(&mut self, name: &str, ty: T) -> &mut Self
where T: Into<Type>,
{
self.bounds.push(Bound {
name: name.to_string(),
bound: vec![ty.into()],
});
self
}
pub fn line<T>(&mut self, line: T) -> &mut Self
where T: ToString,
{
self.body.get_or_insert(vec![])
.push(Body::String(line.to_string()));
self
}
pub fn push_block(&mut self, block: Block) -> &mut Self {
self.body.get_or_insert(vec![])
.push(Body::Block(block));
self
}
pub fn fmt(&self, is_trait: bool, fmt: &mut Formatter) -> fmt::Result {
if let Some(ref docs) = self.docs {
docs.fmt(fmt)?;
}
if let Some(ref allow) = self.allow {
write!(fmt, "#[allow({})]\n", allow)?;
}
if is_trait {
assert!(self.vis.is_none(), "trait fns do not have visibility modifiers");
}
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)?;
match self.body {
Some(ref body) => {
fmt.block(|fmt| {
for b in body {
b.fmt(fmt)?;
}
Ok(())
})
}
None => {
if !is_trait {
panic!("impl blocks must define fn bodies");
}
write!(fmt, ";\n")
}
}
}
}
impl Block {
pub fn new(before: &str) -> Self {
Block {
before: Some(before.to_string()),
after: None,
body: vec![],
}
}
pub fn line<T>(&mut self, line: T) -> &mut Self
where T: ToString,
{
self.body.push(Body::String(line.to_string()));
self
}
pub fn push_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)?;
}
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 {
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 {
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<'a> Formatter<'a> {
pub fn new(dst: &'a mut String) -> Self {
Formatter {
dst,
spaces: 0,
indent: DEFAULT_INDENT,
}
}
fn block<F>(&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(())
}
fn indent<F, R>(&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();
}
should_indent = true;
self.dst.push_str(line);
}
if s.as_bytes().last() == Some(&b'\n') {
self.dst.push_str("\n");
}
Ok(())
}
}