From 70bf1e9d3b4ef3bd5e13a5e7ff20c0765faa19f1 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Tue, 11 Feb 2020 22:06:52 +0100 Subject: [PATCH 01/11] Migrate to syn --- .gitignore | 3 + Cargo.toml | 8 +- src/core/item/mod.rs | 17 +- src/core/item/state/abstraction/enumerate.rs | 75 +++++---- src/core/item/state/abstraction/extend.rs | 91 ++++++----- src/core/item/state/abstraction/mod.rs | 98 +++++------- src/core/item/state/abstraction/structure.rs | 60 +++---- src/core/item/state/implem.rs | 123 ++++++++------- src/core/item/state/method.rs | 136 +++++++++------- src/core/item/state/mod.rs | 153 +++++++++--------- src/core/mod.rs | 62 ++++---- src/core/segment.rs | 4 +- src/lib.rs | 158 +++++++++++-------- src/module/mod.rs | 16 +- tests/aggregation.rs | 4 +- tests/dependency.rs | 2 +- tests/realization.rs | 4 +- 17 files changed, 528 insertions(+), 486 deletions(-) diff --git a/.gitignore b/.gitignore index 4b047b8f..85d2f86b 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,6 @@ Cargo.lock # Graphiz *.dot + +# Idea +.idea \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index c8633deb..029d9473 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,11 +36,9 @@ unstable = [] # for building with unstable features on stable Rust debug = [] # for building with debug messages travis = ["lints", "nightly"] # for building with travis-cargo -[dependencies.syntex_syntax] -version = "0.59" - -[dependencies.syntex_errors] -version = "0.59" +[dependencies] +syn = { features = [ "full", "default", "extra-traits", "derive", "parsing", "printing", "clone-impls", "proc-macro" ], version = "1.0.14" } +quote = "1.0.2" [dependencies.rustc-serialize] version = "0.3" diff --git a/src/core/item/mod.rs b/src/core/item/mod.rs index 88194faf..4546a2f8 100644 --- a/src/core/item/mod.rs +++ b/src/core/item/mod.rs @@ -6,7 +6,6 @@ pub use self::state::ItemState; use std::{slice, iter}; use std::rc::Rc; -use ::syntex_syntax::{ptr, ast}; use ::itertools::Itertools; use ::module::path::ModulePath; @@ -16,13 +15,13 @@ use ::module::path::ModulePath; #[derive(Debug, Clone)] pub struct Item <'a> { /// Iterator. - it: iter::Peekable, Rc)>>, + it: iter::Peekable)>>, } -impl <'a>From, Rc)>>> for Item<'a> { +impl <'a>From)>>> for Item<'a> { /// The constructor method `from` returns a typed and iterable collection of abstract element. - fn from(iter: iter::Peekable, Rc)>>) -> Item { + fn from(iter: iter::Peekable)>>) -> Item { Item { it: iter, } @@ -36,16 +35,16 @@ impl <'a>Iterator for Item<'a> { /// enumeration or trait. fn next(&mut self) -> Option> { self.it.next().and_then(|item| { - let mut list: Vec<&'a (ptr::P, Rc)> = vec!(item); + let mut list: Vec<&'a (syn::Item, Rc)> = vec!(item); - list.extend(self.it.peeking_take_while(|&&(ref item, _): (&&'a (ptr::P, Rc))| { - if let ast::ItemKind::Impl(..) = item.node { + list.extend(self.it.peeking_take_while(|&&(ref item, _): &&'a (syn::Item, Rc)| { + if let syn::Item::Impl(_) = item { true - } else { + } else { false } }) - .collect::, Rc)>>()); + .collect::)>>()); Some(ItemState::from(list)) }) } diff --git a/src/core/item/state/abstraction/enumerate.rs b/src/core/item/state/abstraction/enumerate.rs index ef074498..3fe9aa44 100644 --- a/src/core/item/state/abstraction/enumerate.rs +++ b/src/core/item/state/abstraction/enumerate.rs @@ -1,68 +1,65 @@ use std::fmt; use std::rc::Rc; -use ::syntex_syntax::print::pprust::ty_to_string; -use ::syntex_syntax::{codemap, symbol, ast}; +use ::dot::escape_html; +use syn::{Field, TypeParam, Variant}; +use syn::export::ToTokens; use ::module::path::ModulePath; -use ::dot::escape_html; - /// The structure `Enum` is a enumerate abstract element. - #[derive(Debug, Eq, PartialEq, Clone)] pub struct Enum<'a> { pub path: Rc, /// Visibility - pub vis: &'a ast::Visibility, - pub name: symbol::InternedString, - pub params: Vec, - pub variants: Vec<(symbol::InternedString, Vec)>, + pub vis: &'a syn::Visibility, + pub name: String, + pub params: Vec, + pub variants: Vec<(String, Vec)>, } -impl <'a>From<((&'a ast::Item, &'a Vec, &'a Vec), Rc)> for Enum<'a> { - fn from(((item, ty_params, variants), path): ((&'a ast::Item, &'a Vec, &'a Vec), Rc)) -> Enum<'a> { +impl<'a> From<((&'a syn::ItemEnum, &'a Vec, &'a Vec), Rc)> for Enum<'a> { + fn from(((item, ty_params, variants), path): ((&'a syn::ItemEnum, &'a Vec, &'a Vec), Rc)) -> Enum<'a> { Enum { - path: path, + path, vis: &item.vis, - name: item.ident.name.as_str(), + name: item.ident.to_string(), params: ty_params.iter() - .map(|&ast::TyParam {attrs: _, ident: ast::Ident {name, ..}, ..}| name.as_str()) - .collect::>(), + .map(|param| param.ident.to_string()) + .collect(), variants: variants.iter() - .map(|&codemap::Spanned {node: ast::Variant_ {name: ast::Ident {name, ..}, attrs: _, ref data, ..}, ..}| { - if let &ast::VariantData::Tuple(ref struct_field, _) = data { - (name.as_str(), - struct_field.iter() - .filter_map(|&ast::StructField { span: _, ident: _, vis: _, id: _, ref ty, .. }| Some(ty_to_string(&ty))) - .collect::>()) - } else { - (name.as_str(), Vec::new()) - } - }) - .collect::)>>(), + .map(|Variant { ident, fields, .. }| + (ident.to_string(), if fields.is_empty() { + vec![] + } else { + fields.iter() + .map(|Field { ty, .. }| + ty.to_token_stream().to_string() + ).collect() + })) + .collect(), } } } -impl <'a>fmt::Display for Enum<'a> { +impl<'a> fmt::Display for Enum<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.variants.is_empty() { write!(f, "<<<Enumeration>>>\n{name}", name = self.name) } else { write!(f, "<<<Enumeration>>>\n{name}|{variants}", - name = self.name, - variants = escape_html(self.variants.iter() - .map(|&(ref name, ref struct_field): &(symbol::InternedString, Vec)| - if struct_field.is_empty() { - format!("{}", name) - } else { - format!("{}({})", name, struct_field.join(", ")) - } - ) - .collect::>() - .join("\n") - .as_str()), + name = self.name, + variants = escape_html(self.variants.iter() + .map(|&(ref name, ref struct_field): &(String, Vec)| + if struct_field.is_empty() { + format!("{}", name) + } else { + format!("{}({})", name, struct_field.join(", ")) + } + ) + .collect::>() + .join("\n") + .as_str()), ) } } diff --git a/src/core/item/state/abstraction/extend.rs b/src/core/item/state/abstraction/extend.rs index 21ab97bc..2ef943cb 100644 --- a/src/core/item/state/abstraction/extend.rs +++ b/src/core/item/state/abstraction/extend.rs @@ -1,64 +1,77 @@ use std::fmt; -use std::ops::Deref; use std::rc::Rc; -use ::syntex_syntax::print::pprust::ty_to_string; -use ::syntex_syntax::{symbol, ast}; +use ::dot::escape_html; +use syn::{FnArg, ItemTrait, PatType, Receiver, ReturnType, Signature, TraitItem, TraitItemMethod, TypeParam, Visibility}; +use syn::export::ToTokens; use ::module::path::ModulePath; -use ::dot::escape_html; - #[derive(Debug, Eq, PartialEq, Clone)] pub struct Trait<'a> { pub path: Rc, /// Visibility - pub vis: &'a ast::Visibility, - pub name: symbol::InternedString, - pub params: Vec, - pub items: Vec<(symbol::InternedString, Vec, String)>, + pub vis: &'a Visibility, + pub name: String, + pub params: Vec, + pub items: Vec<(String, Vec, String)>, } -impl <'a>From<((&'a ast::Item, &'a Vec, &'a Vec), Rc)> for Trait<'a> { - fn from(((item, ty_params, trait_item), path): ((&'a ast::Item, &'a Vec, &'a Vec), Rc)) -> Trait<'a> { +impl<'a> From<((&'a ItemTrait, &'a Vec, &'a Vec), Rc)> for Trait<'a> { + fn from(((item, ty_params, trait_item), path): ((&'a ItemTrait, &'a Vec, &'a Vec), Rc)) -> Trait<'a> { Trait { - path: path, + path, vis: &item.vis, - name: item.ident.name.as_str(), + name: item.ident.to_string(), params: ty_params.iter() - .map(|&ast::TyParam {attrs: _, ident: ast::Ident {name, ..}, ..}| name.as_str()) - .collect::>(), + .map(|TypeParam { ident, .. }| ident.to_string()) + .collect(), items: trait_item.iter() - .filter_map(|&ast::TraitItem {id: _, ident: ast::Ident {name, ..}, attrs: _, ref node, ..}| - if let &ast::TraitItemKind::Method(ast::MethodSig { unsafety: _, constness: _, abi: _, ref decl, ..}, _) = node { - if let &ast::FnDecl {ref inputs, output: ast::FunctionRetTy::Ty(ref ty), ..} = decl.deref() { - Some((name.as_str(), inputs.iter().map(|input| ty_to_string(&input.ty)).collect::>(), ty_to_string(&ty))) - } else { - None - } - } else { - None - } - ) - .collect::, String)>>() + .filter_map(|item: &TraitItem| + if let TraitItem::Method(TraitItemMethod { sig: Signature { ident, inputs, output: ReturnType::Type(_, output), .. }, .. }) = item { + Some((ident.to_string(), inputs.iter().filter_map(|input| { + dbg!(input); + match input { + FnArg::Typed(PatType { ty, .. }) => { + Some(ty.to_token_stream().to_string()) + } + FnArg::Receiver(Receiver { reference, mutability, .. }) => { // FIXME + let (r1, r2) = match reference { + Some((and, lifetime)) => (Some(and.to_token_stream().to_string()), Some(lifetime.to_token_stream().to_string())), + None => (None, None) + }; + let mutability = Some(mutability.to_token_stream().to_string()); + let s = Some(" Self".into()); + Some([r1, r2, mutability, s].into_iter().flatten().map(ToString::to_string).collect()) + } + _ => { + None + } + } + }).collect(), output.to_token_stream().to_string())) + } else { + None + } + ) + .collect::, String)>>(), } } } -impl <'a>fmt::Display for Trait<'a> { +impl<'a> fmt::Display for Trait<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "<<<Trait>>>\n{name}|{items}", - name = self.name, - items = escape_html(self.items.iter() - .map(|&(ref name, ref ty, ref ret): &(symbol::InternedString, Vec, String)| - format!("{name}({ty}) -> {ret}", - name = name, - ty = ty.join(", "), - ret = ret - )) - .collect::>() - .join("\n") - .as_str()) + name = self.name, + items = escape_html(self.items.iter() + .map(|&(ref name, ref ty, ref ret): &(String, Vec, String)| + format!("{name}({ty}) -> {ret}", + name = name, + ty = ty.join(", "), + ret = ret + )) + .collect::>() + .join("\n") + .as_str()) ) } } diff --git a/src/core/item/state/abstraction/mod.rs b/src/core/item/state/abstraction/mod.rs index a990ae0d..dbac54ad 100644 --- a/src/core/item/state/abstraction/mod.rs +++ b/src/core/item/state/abstraction/mod.rs @@ -1,40 +1,34 @@ -pub mod extend; -pub mod structure; -pub mod enumerate; - use std::fmt; use std::vec; -use std::rc::Rc; - -use ::syntex_syntax::symbol; -use ::core::ast; -use ::module::path::ModulePath; +use syn::Visibility; +use self::enumerate::Enum; use self::extend::Trait; use self::structure::Struct; -use self::enumerate::Enum; -/// The structure `Abstract` is a enumerate for abstract element types or none. +pub mod extend; +pub mod structure; +pub mod enumerate; +/// The structure `Abstract` is a enumerate for abstract element types or none. #[derive(Debug, Eq, PartialEq, Clone)] -pub enum Abstract <'a> { +pub enum Abstract<'a> { Trait(Trait<'a>), Struct(Struct<'a>), Enum(Enum<'a>), None, } -impl <'a> Abstract <'a> { - +impl<'a> Abstract<'a> { /// The method `as_name` returns the name of the abstract element /// or else declare a panic. - pub fn as_name(&self) -> Option<&symbol::InternedString> { + pub fn as_name(&self) -> Option<&String> { match self { - &Abstract::Trait(Trait { vis: _, ref name, ..}) => Some(name), - &Abstract::Struct(Struct { vis: _, ref name, ..}) => Some(name), - &Abstract::Enum(Enum { vis: _, ref name, ..}) => Some(name), - &Abstract::None => None, + Abstract::Trait(Trait { name, .. }) => Some(name), + Abstract::Struct(Struct { name, .. }) => Some(name), + Abstract::Enum(Enum { name, .. }) => Some(name), + Abstract::None => None, } } } @@ -45,60 +39,40 @@ impl<'a> IntoIterator for &'a Abstract<'a> { fn into_iter(self) -> Self::IntoIter { match self { - &Abstract::Struct(Struct {path: _, vis: _, name: _, fields: ref ty_field}) => { - ty_field.iter() - .map(|&(_, _, ref ty): &'a (&'a ast::Visibility, symbol::InternedString, String)| ty) - .collect::>() - .into_iter() - }, - &Abstract::Enum(Enum {path: _, vis: _, name: _, params: _, variants: ref ty_multi_field}) => { - ty_multi_field.iter() - .map(|&(_, ref ty_field): &'a (symbol::InternedString, Vec)| - ty_field.iter() - .map(|ty: &'a String| ty) - .collect::>()) - .collect::>>() - .concat() - .into_iter() - }, - _ => { - Vec::default().into_iter() - }, + Abstract::Struct(Struct { fields, .. }) => { + fields.iter() + .map(|&(_, _, ref ty): &'a (&'a Visibility, String, String)| ty) + .collect::>() + .into_iter() + } + Abstract::Enum(Enum { variants, .. }) => { + variants.iter() + .map(|&(_, ref ty_field): &'a (String, Vec)| + ty_field.iter() + .map(|ty: &'a String| ty) + .collect::>()) + .collect::>>() + .concat() + .into_iter() + } + _ => Vec::default().into_iter(), } } } -impl <'a> Default for Abstract<'a> { +impl<'a> Default for Abstract<'a> { fn default() -> Abstract<'a> { Abstract::None } } -impl <'a>From<((&'a ast::Item, &'a Vec, &'a Vec), Rc)> for Abstract<'a> { - fn from(arguments: ((&'a ast::Item, &'a Vec, &'a Vec), Rc)) -> Abstract<'a> { - Abstract::Trait(Trait::from(arguments)) - } -} - -impl <'a>From<((&'a ast::Item, &'a Vec), Rc)> for Abstract<'a> { - fn from(arguments: ((&'a ast::Item, &'a Vec), Rc)) -> Abstract<'a> { - Abstract::Struct(Struct::from(arguments)) - } -} - -impl <'a>From<((&'a ast::Item, &'a Vec, &'a Vec), Rc)> for Abstract<'a> { - fn from(arguments: ((&'a ast::Item, &'a Vec, &'a Vec), Rc)) -> Abstract<'a> { - Abstract::Enum(Enum::from(arguments)) - } -} - -impl <'a>fmt::Display for Abstract<'a> { +impl<'a> fmt::Display for Abstract<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - &Abstract::Struct(ref item) => write!(f, "{}", item), - &Abstract::Enum(ref item) => write!(f, "{}", item), - &Abstract::Trait(ref item) => write!(f, "{}", item), - &Abstract::None => Err(fmt::Error), + Abstract::Struct(item) => write!(f, "{}", item), + Abstract::Enum(item) => write!(f, "{}", item), + Abstract::Trait(item) => write!(f, "{}", item), + Abstract::None => Err(fmt::Error), } } } diff --git a/src/core/item/state/abstraction/structure.rs b/src/core/item/state/abstraction/structure.rs index 6bac5616..6e67d546 100644 --- a/src/core/item/state/abstraction/structure.rs +++ b/src/core/item/state/abstraction/structure.rs @@ -1,56 +1,58 @@ use std::fmt; +use std::fmt::{Debug, Formatter}; use std::rc::Rc; -use ::syntex_syntax::print::pprust::ty_to_string; -use ::syntex_syntax::{symbol, ast}; +use ::dot::escape_html; +use syn::{Field, ItemStruct, Visibility}; +use syn::export::ToTokens; use ::module::path::ModulePath; -use ::dot::escape_html; - /// The structure `Struct` is a structure abstract element. - #[derive(Debug, Eq, PartialEq, Clone)] pub struct Struct<'a> { pub path: Rc, /// Visibility - pub vis: &'a ast::Visibility, - pub name: symbol::InternedString, - pub fields: Vec<(&'a ast::Visibility, symbol::InternedString, String)>, + pub vis: &'a Visibility, + pub name: String, + pub fields: Vec<(&'a Visibility, String, String)>, } -impl <'a>From<((&'a ast::Item, &'a Vec), Rc)> for Struct<'a> { - fn from(((item, struct_field), path): ((&'a ast::Item, &'a Vec), Rc)) -> Struct<'a> { +impl<'a> From<((&'a ItemStruct, &'a Vec), Rc)> for Struct<'a> { + fn from(((item, struct_field), path): ((&'a ItemStruct, &'a Vec), Rc)) -> Struct<'a> { Struct { - path: path, + path, vis: &item.vis, - name: item.ident.name.as_str(), + name: item.ident.to_string(), fields: struct_field.iter() - .filter_map(|&ast::StructField { span: _, ident, ref vis, id: _, ref ty, .. }| - ident.and_then(|ast::Ident {name, ..}| Some((vis, name.as_str(), ty_to_string(&ty))))) - .collect::>() + .enumerate() + .map(|(index, Field { vis, ident, ty, .. })| { + let ident = if let Some(ident) = ident { ident.to_string() } else { index.to_string() }; + (vis, ident, ty.to_token_stream().to_string()) + }) + .collect(), } } } -impl <'a>fmt::Display for Struct<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl<'a> fmt::Display for Struct<'a> { + fn fmt(&self, f: &mut Formatter) -> fmt::Result { if self.fields.is_empty() { write!(f, "<<<Structure>>>\n{name}", name = self.name) } else { write!(f, "<<<Structure>>>\n{name}|{fields}", - name = self.name, - fields = escape_html(self.fields.iter() - .map(|&(ref vis, ref name, ref ty): &(&ast::Visibility, symbol::InternedString, String)| - if ast::Visibility::Public.eq(vis) { - format!("+ {name}: {ty}", name = name, ty = ty) - } else { - format!("- {name}: {ty}", name = name, ty = ty) - } - ) - .collect::>() - .join("\n") - .as_str()), + name = self.name, + fields = escape_html(self.fields.iter() + .map(|&(ref vis, ref name, ref ty): &(&Visibility, String, String)| + if let Visibility::Public(_) = vis { + format!("+ {name}: {ty}", name = name, ty = ty) + } else { + format!("- {name}: {ty}", name = name, ty = ty) + } + ) + .collect::>() + .join("\n") + .as_str()), ) } } diff --git a/src/core/item/state/implem.rs b/src/core/item/state/implem.rs index 8a4a50eb..11166db3 100644 --- a/src/core/item/state/implem.rs +++ b/src/core/item/state/implem.rs @@ -1,21 +1,19 @@ -use super::DEFAULT_FUNC; - -use std::ops::Deref; use std::fmt; -use ::syntex_syntax::print::pprust::ty_to_string; -use ::syntex_syntax::symbol::InternedString; -use ::syntex_syntax::ast; - use ::dot::escape_html; +use syn::{AngleBracketedGenericArguments, FnArg, GenericArgument, ImplItem, ImplItemMethod, PathArguments, PathSegment, ReturnType, Signature}; +use syn::export::ToTokens; +use syn::punctuated::Punctuated; +use syn::token::Colon2; -/// The structure `Implem` is a collection of methods and tyes for an abstract element. +use super::DEFAULT_FUNC; +/// The structure `Implem` is a collection of methods and tyes for an abstract element. #[derive(Default, Debug, Clone, Eq, PartialEq)] pub struct Implem { - ty: Vec<(InternedString, Vec)>, + ty: Vec<(String, Vec)>, /// method's name, arguments, result. - method: Vec<(InternedString, Vec, Option)>, + method: Vec<(String, Vec, Option)>, } impl Implem { @@ -29,26 +27,26 @@ impl Implem { pub fn is_association(&self, ty_name: &String) -> bool { self.method.iter() - .any(|&(_, _, ref result): &(InternedString, Vec, Option)| - if let &Some(ref ret) = result { - ret.split(|at| "<[(;, )]>".contains(at)) - .any(|ty| ty.eq(ty_name)) - } else { - false - } - ) + .any(|&(_, _, ref result): &(String, Vec, Option)| + if let &Some(ref ret) = result { + ret.split(|at| "<[(;, )]>".contains(at)) + .any(|ty| ty.eq(ty_name)) + } else { + false + } + ) } pub fn is_dependency(&self, _: &String) -> bool { false /*self.method.iter() - .any(|&( _, ref arg, _): &(InternedString, Vec, Option)| + .any(|&( _, ref arg, _): &(String, Vec, Option)| arg.iter().any(|ty| ty.ends_with(name)))*/ } } -impl From<(Vec<(InternedString, Vec)>, Vec<(InternedString, Vec, Option)>)> for Implem { - fn from((ty, method): (Vec<(InternedString, Vec)>, Vec<(InternedString, Vec, Option)>)) -> Implem { +impl From<(Vec<(String, Vec)>, Vec<(String, Vec, Option)>)> for Implem { + fn from((ty, method): (Vec<(String, Vec)>, Vec<(String, Vec, Option)>)) -> Implem { Implem { ty: ty, method: method, @@ -56,52 +54,61 @@ impl From<(Vec<(InternedString, Vec)>, Vec<(InternedString, Vec, } } -impl <'a> From<(&'a Vec, &'a Vec)> for Implem { - fn from((segments, impl_item): (&'a Vec, &'a Vec)) -> Implem { +impl<'a> From<(&'a Punctuated, &'a Vec)> for Implem { + fn from((segments, impl_item): (&'a Punctuated, &'a Vec)) -> Implem { Implem::from((segments.iter() - .map(|&ast::PathSegment { identifier: ast::Ident {name, ..}, span: _, ref parameters }| { - if let &Some(ref path) = parameters { - if let &ast::PathParameters::AngleBracketed( - ast::AngleBracketedParameterData { lifetimes: _, ref types, .. } - ) = path.deref() { - (name.as_str(), types.iter().map(|ty| ty_to_string(&ty)).collect::>()) - } else { - (name.as_str(), Vec::new()) - } + .map(|PathSegment { ident, arguments, .. }| { + if let PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }) = arguments { + (ident.to_string(), args.iter() + .filter_map(|ty| + if let GenericArgument::Type(ty) = ty { + Some(ty.to_token_stream().to_string()) + } else { + None + }) + .collect::>()) + } else { + (ident.to_string(), Vec::new()) + } + }) + .collect::)>>(), + impl_item.iter() + .filter_map(|item| { + if let ImplItem::Method(ImplItemMethod { sig: Signature { ident, inputs, output, .. }, .. }) = item { + let inputs = inputs.iter() + .filter_map(|arg| + if let FnArg::Typed(ty) = arg { + Some(ty.ty.to_token_stream().to_string()) + } else { + None + }) + .collect(); + if let ReturnType::Type(_, ref ty) = output { + Some((ident.to_string(), inputs, Some(ty.to_token_stream().to_string()))) } else { - (name.as_str(), Vec::new()) + Some((ident.to_string(), inputs, None)) } - }) - .collect::)>>(), - impl_item.iter() - .filter_map(|&ast::ImplItem { id: _, ident: ast::Ident {name, ..}, vis: _, defaultness: _, attrs: _, ref node, ..}| - if let &ast::ImplItemKind::Method(ast::MethodSig { unsafety: _, constness: _, abi: _, ref decl, .. }, _) = node { - if let ast::FunctionRetTy::Ty(ref ty) = decl.output { - Some((name.as_str(), decl.inputs.iter().map(|arg| ty_to_string(&arg.ty)).collect::>(), Some(ty_to_string(&ty)))) - } else { - Some((name.as_str(), decl.inputs.iter().map(|arg| ty_to_string(&arg.ty)).collect::>(), None)) - } - } else { - None - } - ).collect::, Option)>>())) + } else { + None + } + }).collect::, Option)>>())) } } impl fmt::Display for Implem { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{item}", - item = escape_html(self.method.iter() - .map(|&(ref name, ref args, ref result): &(InternedString, Vec, Option)| { - if let &Some(ref ret) = result { - format!("{}{}({}) -> {}", DEFAULT_FUNC, name, args.join(", "), ret) - } else { - format!("{}{}({})", DEFAULT_FUNC, name, args.join(", ")) - } - }) - .collect::>() - .join("\n") - .as_str())) + item = escape_html(self.method.iter() + .map(|&(ref name, ref args, ref result): &(String, Vec, Option)| { + if let &Some(ref ret) = result { + format!("{}{}({}) -> {}", DEFAULT_FUNC, name, args.join(", "), ret) + } else { + format!("{}{}({})", DEFAULT_FUNC, name, args.join(", ")) + } + }) + .collect::>() + .join("\n") + .as_str())) /*if let Some(&(ref name, ref template)) = self.ty.last() { if template.is_empty() { write!(f, "{name}", name = name.to_string()) diff --git a/src/core/item/state/method.rs b/src/core/item/state/method.rs index ae2a6903..3bc65faa 100644 --- a/src/core/item/state/method.rs +++ b/src/core/item/state/method.rs @@ -1,48 +1,63 @@ -use super::DEFAULT_FUNC; - -use std::ops::Deref; use std::fmt; use std::rc::Rc; -use ::syntex_syntax::print::pprust::{ty_to_string, arg_to_string}; -use ::syntex_syntax::symbol::InternedString; -use ::syntex_syntax::ast; +use ::dot::escape_html; +use syn::{ + export::ToTokens, + FnArg, + ImplItem, + ImplItemMethod, + punctuated::Punctuated, + ReturnType, + Signature, + token::Comma, + Type, + Visibility, +}; use ::module::path::ModulePath; -use ::dot::escape_html; +use super::DEFAULT_FUNC; /// The structure `Method` is a collection of methods from a abstract element. - #[derive(Default, Debug, Clone, Eq, PartialEq)] -pub struct Method <'a> { +pub struct Method<'a> { /// visibility, method's name, arguments, result. - func: Vec<(&'a ast::Visibility, InternedString, Vec, Option)>, + func: Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, path: Rc, } -impl <'a> Method <'a> { +impl<'a> Method<'a> { pub fn is_association(&self, ty_name: &String) -> bool { self.func.iter() - .any(|&(_, _, _, ref result): &(&'a ast::Visibility, InternedString, Vec, Option)| - if let &Some(ref ret) = result { - ret.split(|at| "<[(;, )]>".contains(at)) - .any(|ty| ty.eq(ty_name)) - } else { - false - } - ) + .any(|&(_, _, _, ref result)| + if let &Some(ret) = result { + // TODO: replace by checking if ret (which is of type Type) + // TODO: contains ty_name anywhere + ret.to_token_stream().to_string().split(|at| "<[(;, )]>".contains(at)) + .any(|ty| ty.eq(ty_name)) + } else { + false + } + ) } pub fn is_dependency(&self, name: &String) -> bool { self.func.iter() - .any(|&(_, _, ref arg, _): &(&'a ast::Visibility, InternedString, Vec, Option)| - arg.iter().any(|ty| ty.ends_with(name))) + .any(|&(_, _, ref arg, _): &(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)| + arg.iter().filter_map(|ty| { + if let FnArg::Typed(ty) = ty { + Some(ty) + } else { + None + } + }) + .any(|ty| ty.ty.to_token_stream().to_string().ends_with(name))) } } -impl <'a> From<(Vec<(&'a ast::Visibility, InternedString, Vec, Option)>, Rc)> for Method<'a> { - fn from((func, path): (Vec<(&'a ast::Visibility, InternedString, Vec, Option)>, Rc)) -> Method<'a> { +impl<'a> From<(Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, Rc)> for Method<'a> { + fn from((func, path): (Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, Rc)) -> Method<'a> { Method { func: func, path: path, @@ -50,50 +65,51 @@ impl <'a> From<(Vec<(&'a ast::Visibility, InternedString, Vec, Option From<(&'a Vec, Rc)> for Method<'a> { - fn from((impl_item, path): (&'a Vec, Rc)) -> Method<'a> { +impl<'a> From<(&'a Vec, Rc)> for Method<'a> { + fn from((impl_item, path): (&'a Vec, Rc)) -> Method<'a> { Method::from((impl_item.iter() - .filter_map(|&ast::ImplItem {id: _, ident: ast::Ident { name, ..}, ref vis, defaultness: _, attrs: _, ref node, .. }| { - if let &ast::ImplItemKind::Method(ast::MethodSig {unsafety: _, constness: _, abi: _, ref decl, ..}, _) = node { - if let &ast::FnDecl {ref inputs, output: ast::FunctionRetTy::Ty(ref ty), ..} = decl.deref() { - Some((vis, name.as_str(), inputs.iter().map(|ref arg| arg_to_string(&arg)).collect::>(), Some(ty_to_string(&ty)))) - } else if let &ast::FnDecl {ref inputs, output: ast::FunctionRetTy::Default(_), ..} = decl.deref() { - Some((vis, name.as_str(), inputs.iter().map(|ref arg| arg_to_string(&arg)).collect::>(), None)) - } else { - None - } - } else { - None - } - }) - .collect::, Option)>>(), + .filter_map(|item| { + if let ImplItem::Method(ImplItemMethod { ref vis, ref sig, .. }) = item { + if let Signature { ident, inputs, output: ReturnType::Default, .. } = sig { + Some((vis, ident.to_string(), inputs, None)) + } else if let Signature { ident, inputs, output: ReturnType::Type(_, ref output), .. } = sig { + Some((vis, ident.to_string(), inputs, Some(output))) + } else { + None + } + } else { + None + } + }) + .collect::>(), path)) } } -impl <'a>fmt::Display for Method<'a> { +impl<'a> fmt::Display for Method<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{item}", - item = escape_html(self.func.iter() - .map(|&(ref vis, ref name, ref inputs, ref ty)| - match (vis, ty) { - (&&ast::Visibility::Public, &Some(ref ty)) => { - format!("+{}{}({}) -> {}", DEFAULT_FUNC, name, inputs.iter().map(|arg| arg.to_string()).collect::>().join(", "), ty) - }, - (&&ast::Visibility::Public, &None) => { - format!("+{}{}({})", DEFAULT_FUNC, name, inputs.iter().map(|arg| arg.to_string()).collect::>().join(", ")) - }, - (_, &Some(ref ty)) => { - format!("-{}{}({}) -> {}", DEFAULT_FUNC, name, inputs.iter().map(|arg| arg.to_string()).collect::>().join(", "), ty) - }, - (_, &None) => { - format!("-{}{}({})", DEFAULT_FUNC, name, inputs.iter().map(|arg| arg.to_string()).collect::>().join(", ")) - }, - } - ) - .collect::>() - .join("\n") - .as_str()) + item = escape_html(self.func.iter() + .map(|&(vis, ref name, ref inputs, ty)| { + match (vis, ty) { + (Visibility::Public(_), Some(ty)) => { + format!("+{}{}({}) -> {}", DEFAULT_FUNC, name, inputs.to_token_stream().to_string(), ty.to_token_stream().to_string()) + } + (Visibility::Public(_), None) => { + format!("+{}{}({})", DEFAULT_FUNC, name, inputs.to_token_stream().to_string()) + } + (_, Some(ty)) => { + format!("-{}{}({}) -> {}", DEFAULT_FUNC, name, inputs.to_token_stream().to_string(), ty.to_token_stream().to_string()) + } + (_, None) => { + format!("-{}{}({})", DEFAULT_FUNC, name, inputs.to_token_stream().to_string()) + } + } + } + ) + .collect::>() + .join("\n") + .as_str()) ) } } diff --git a/src/core/item/state/mod.rs b/src/core/item/state/mod.rs index 195e012b..19fc4d3d 100644 --- a/src/core/item/state/mod.rs +++ b/src/core/item/state/mod.rs @@ -1,3 +1,17 @@ +use std::fmt; +use std::ops::BitOr; +use std::rc::Rc; + +use syn::{Field, Item, ItemEnum, ItemImpl, ItemTrait, Path, TraitItem, TypeParam, Variant}; + +use ::module::path::ModulePath; + +use super::relation::Relation; + +use self::abstraction::Abstract; +use self::implem::Implem; +use self::method::Method; + pub mod abstraction; pub mod implem; pub mod method; @@ -7,21 +21,6 @@ const DEFAULT_FUNC: &'static str = " "; #[cfg(feature = "fn-emilgardis")] const DEFAULT_FUNC: &'static str = " fn "; -use self::abstraction::Abstract; -use self::implem::Implem; -use self::method::Method; - -use super::relation::Relation; - -use std::ops::BitOr; -use std::fmt; -use std::rc::Rc; - -use ::syntex_syntax::symbol::InternedString; -use ::syntex_syntax::{ptr, ast}; - -use ::module::path::ModulePath; - /// The structure `ItemState` describes an abstract element with a collections of methodes /// and implementations. #[derive(Default, Debug, Clone, Eq, PartialEq)] @@ -34,8 +33,7 @@ pub struct ItemState<'a> { implem: Vec, } -impl <'a> ItemState <'a> { - +impl<'a> ItemState<'a> { pub fn is_none(&self) -> bool { self.node.eq(&Abstract::None) } @@ -45,9 +43,9 @@ impl <'a> ItemState <'a> { let ref ty_name: String = name.to_string(); rhs.method.iter() - .any(|func| func.is_association(ty_name)) - .bitor(rhs.implem.iter() - .any(|implem| implem.is_association(&ty_name))) + .any(|func| func.is_association(ty_name)) + .bitor(rhs.implem.iter() + .any(|implem| implem.is_association(&ty_name))) } else { false } @@ -58,25 +56,25 @@ impl <'a> ItemState <'a> { let ref ty_name: String = name.to_string(); rhs.method.iter() - .any(|method| method.is_dependency(&ty_name)) - .bitor(self.implem.iter() - .any(|implem| implem.is_dependency(&ty_name))) + .any(|method| method.is_dependency(&ty_name)) + .bitor(self.implem.iter() + .any(|implem| implem.is_dependency(&ty_name))) } else { false } } pub fn is_aggregation(&self, rhs: &ItemState<'a>) -> bool { - if let Some(ref name) = self.as_name() { - let mut ty_name_mut: String = String::from("*mut "); - let mut ty_name_const: String = String::from("*const "); - + if let Some(name) = self.as_name() { + let mut ty_name_mut: String = String::from("* mut "); + let mut ty_name_const: String = String::from("* const "); + ty_name_mut.push_str(&name); ty_name_const.push_str(&name); rhs.node.into_iter() - .any(|attribut: &String| - attribut.split(|at| "<[(;,)]>".contains(at)) - .any(|ty| ty_name_mut.eq(ty).bitor(ty_name_const.eq(ty)))) + .any(|attribut: &String| + attribut.split(|at| "<[(;,)]>".contains(at)) + .any(|ty| ty_name_mut.eq(ty).bitor(ty_name_const.eq(ty)))) } else { false } @@ -87,9 +85,9 @@ impl <'a> ItemState <'a> { let ty_name: String = name.to_string(); rhs.node.into_iter() - .any(|attribut: &String| - attribut.split(|at| "<[(;,)]>".contains(at)) - .any(|ty| ty.eq(&ty_name))) + .any(|attribut: &String| + attribut.split(|at| "<[(;,)]>".contains(at)) + .any(|ty| ty.eq(&ty_name))) } else { false } @@ -100,7 +98,7 @@ impl <'a> ItemState <'a> { let ty_name: String = name.to_string(); rhs.implem.iter() - .any(|implem| implem.is_realization(&ty_name)) + .any(|implem| implem.is_realization(&ty_name)) } else { false } @@ -114,7 +112,7 @@ impl <'a> ItemState <'a> { .bitor(self.is_realization(rhs)) } - pub fn as_name(&self) -> Option<&InternedString> { + pub fn as_name(&self) -> Option<&String> { self.node.as_name() } @@ -123,72 +121,77 @@ impl <'a> ItemState <'a> { } } -impl <'a>From<(Abstract<'a>, Vec<&'a (ptr::P, Rc)>)> for ItemState<'a> { - fn from((node, properties): (Abstract<'a>, Vec<&'a (ptr::P, Rc)>)) -> ItemState<'a> { +impl<'a> From<(Abstract<'a>, Vec<&'a (Item, Rc)>)> for ItemState<'a> { + fn from((node, properties): (Abstract<'a>, Vec<&'a (Item, Rc)>)) -> ItemState<'a> { ItemState { - node: node, + node, method: properties.iter() - .filter_map(|&&(ref item, ref path): (&&'a (ptr::P, Rc))| - if let ast::ItemKind::Impl(_, _, _, _, None, _, ref impl_item) = item.node { - Some(Method::from((impl_item, Rc::clone(path)))) + .filter_map(|&&(ref item, ref path): &&'a (Item, Rc)| + if let Item::Impl(ItemImpl { trait_: None, items, .. }) = item { + Some(Method::from((items, Rc::clone(path)))) } else { None } ) - .collect::>(), + .collect(), implem: properties.iter() - .filter_map(|&&(ref item, _): (&&'a (ptr::P, Rc))| - if let ast::ItemKind::Impl(_, _, _, _, Some(ast::TraitRef {path: ast::Path {span: _, ref segments}, ..}), _, ref impl_item) = item.node { - Some(Implem::from((segments, impl_item))) + .filter_map(|&&(ref item, _): &&'a (Item, Rc)| + if let Item::Impl(ItemImpl { trait_: Some((_, Path { segments, .. }, _)), items, .. }) = item { + Some(Implem::from((segments, items))) } else { None } ) - .collect::>() + .collect(), } } } -impl <'a>From, Rc)>> for ItemState<'a> { - fn from(state: Vec<&'a (ptr::P, Rc)>) -> ItemState<'a> { - state.split_first().and_then(|(&&(ref item, ref path), properties): (&&'a (ptr::P, Rc), &[&'a (ptr::P, Rc)])| { - match &item.node { +impl<'a> From)>> for ItemState<'a> { + fn from(state: Vec<&'a (Item, Rc)>) -> ItemState<'a> { + state.split_first().and_then(|(&&(ref item, ref path), properties): (&&'a (Item, Rc), &[&'a (Item, Rc)])| { + match &item { /// Trait. - &ast::ItemKind::Trait(_, ast::Generics {lifetimes: _, ref ty_params, ..}, _, ref trait_item) => { - let kind: (&'a ast::Item, &'a Vec, &'a Vec) = (item, ty_params, trait_item); - let kind: (Abstract, Vec<&'a (ptr::P, Rc)>) = (Abstract::from((kind, Rc::clone(path))), properties.to_vec()); + &Item::Trait(item) => { + let ItemTrait { generics, items, .. } = item; + let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME + let kind: (_, &'a Vec, &'a Vec) = (item, ty_params, items); + let kind: (Abstract, Vec<&'a (Item, Rc)>) = (Abstract::Trait((kind, Rc::clone(path)).into()), properties.to_vec()); Some(ItemState::from(kind)) - }, + } /// Structure with variables. - &ast::ItemKind::Struct(ast::VariantData::Struct(ref struct_field, _), ..) => { - let kind: (&'a ast::Item, &'a Vec) = (item, struct_field); - let kind: (Abstract, Vec<&'a (ptr::P, Rc)>) = (Abstract::from((kind, Rc::clone(path))), properties.to_vec()); + &Item::Struct(item) => { + let fields = Box::leak(Box::new(item.fields.iter().cloned().collect())); // FIXME + let kind: (_, &Vec) = (item, fields); + let kind = (Abstract::Struct((kind, Rc::clone(path)).into()), properties.to_vec()); Some(ItemState::from(kind)) - }, + } /// Enumeration with variables. - &ast::ItemKind::Enum(ast::EnumDef {ref variants}, ast::Generics {lifetimes: _, ref ty_params, ..}) => { - let kind: (&'a ast::Item, &'a Vec, &'a Vec) = (item, ty_params, variants); - let kind: (Abstract, Vec<&'a (ptr::P, Rc)>) = (Abstract::from((kind, Rc::clone(path))), properties.to_vec()); + &Item::Enum(item) => { + let ItemEnum { generics, variants, .. } = item; + let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME + let variants = Box::leak(Box::new(variants.iter().cloned().collect())); // FIXME + let kind: (&'a ItemEnum, &'a Vec, &'a Vec) = (item, ty_params, variants); + let kind: (Abstract, Vec<&'a (Item, Rc)>) = (Abstract::Enum((kind, Rc::clone(path)).into()), properties.to_vec()); Some(ItemState::from(kind)) - }, + } _ => None, } }).unwrap_or_default() } } -impl <'a>fmt::Display for ItemState<'a> { - +impl<'a> fmt::Display for ItemState<'a> { #[cfg(feature = "implem")] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{{{node}|{method}|{implem}}}", - node = self.node, - method = self.method.iter() - .map(|ref methods| format!("{}", methods)) - .collect::>().join("\n").as_str(), - implem = self.implem.iter() - .map(|ref implem| format!("{}", implem)) - .collect::>().join("\n").as_str()) + node = self.node, + method = self.method.iter() + .map(|ref methods| format!("{}", methods)) + .collect::>().join("\n").as_str(), + implem = self.implem.iter() + .map(|ref implem| format!("{}", implem)) + .collect::>().join("\n").as_str()) } #[cfg(not(feature = "implem"))] @@ -197,10 +200,10 @@ impl <'a>fmt::Display for ItemState<'a> { write!(f, "{{{node}}}", node = self.node) } else { write!(f, "{{{node}|{method}}}", - node = self.node, - method = self.method.iter() - .map(|ref methods| format!("{}", methods)) - .collect::>().join("\n").as_str()) + node = self.node, + method = self.method.iter() + .map(|ref methods| format!("{}", methods)) + .collect::>().join("\n").as_str()) } } } diff --git a/src/core/mod.rs b/src/core/mod.rs index 43468179..2eee057a 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,43 +1,42 @@ //! Core Syntax and definitions. -pub mod segment; -pub mod item; - -use self::segment::Segment; -use self::item::{Item, ItemState}; -use self::item::relation::Relation; - -use std::{slice, iter}; +use std::{iter, slice}; use std::borrow::Cow; use std::ops::BitOr; use std::rc::Rc; -use ::syntex_syntax::{ptr, ast}; -use ::dot::{Nodes, Edges, Arrow, Style, GraphWalk, Labeller, LabelText, Id}; +use ::dot::{Arrow, Edges, GraphWalk, Id, Labeller, LabelText, Nodes, Style}; use ::itertools::Itertools; use ::module::path::ModulePath; +use self::item::{Item, ItemState}; +use self::item::relation::Relation; +use self::segment::Segment; + +pub mod segment; +pub mod item; + #[derive(Debug, Clone)] -pub struct ListItem <'a> { +pub struct ListItem<'a> { parse: Item<'a>, } -impl <'a> From> for ListItem <'a> { - fn from(parse: Item<'a>) -> ListItem <'a> { +impl<'a> From> for ListItem<'a> { + fn from(parse: Item<'a>) -> ListItem<'a> { ListItem { - parse: parse, + parse, } } } -impl <'a> From, Rc)>>> for ListItem <'a> { - fn from(list: iter::Peekable, Rc)>>) -> ListItem <'a> { +impl<'a> From)>>> for ListItem<'a> { + fn from(list: iter::Peekable)>>) -> ListItem<'a> { ListItem::from(Item::from(list)) } } -impl <'a>Iterator for ListItem<'a> { +impl<'a> Iterator for ListItem<'a> { type Item = ItemState<'a>; fn next(&mut self) -> Option> { @@ -88,21 +87,26 @@ impl<'a> GraphWalk<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> { fn nodes(&'a self) -> Nodes<'a, ItemState<'a>> { Cow::Owned(self.clone().collect::>>()) } - + fn edges(&'a self) -> Edges<'a, Segment<'a>> { let items = self.clone().collect::>>(); - Cow::Owned(items.iter() - .map(|item| items.iter() - .filter(|rhs| item.ne(rhs)) - .filter(|rhs| item.is_relation(rhs)) - .map(|rhs| Segment::from((item.clone(), rhs.clone()))) - .collect::>>()) - .collect::>>>() - .concat() - .into_iter() - .unique() - .collect::>>()) + let dbg = items.iter().map(|s| format!("{:?}", s)).collect::>(); + println!("{:#?}", dbg); + + let items = items.iter() + .map(|item| items.iter() + .filter(|rhs| item.ne(rhs)) + .filter(|rhs| item.is_relation(rhs)) + .map(|rhs| Segment::from((item.clone(), rhs.clone()))) + .collect::>>()) + .collect::>>>() + .concat() + .into_iter() + .unique() + .collect::>>(); + + Cow::Owned(items) } fn source(&self, seg: &Segment<'a>) -> ItemState<'a> { seg.left.clone() } diff --git a/src/core/segment.rs b/src/core/segment.rs index ecf01f29..d1fcf1ec 100644 --- a/src/core/segment.rs +++ b/src/core/segment.rs @@ -14,8 +14,8 @@ pub struct Segment<'a> { impl <'a> From<(ItemState<'a>, ItemState<'a>)> for Segment <'a> { fn from((left, right): (ItemState<'a>, ItemState<'a>)) -> Segment<'a> { Segment { - left: left, - right: right, + left, + right, } } } diff --git a/src/lib.rs b/src/lib.rs index 3f66c809..d2638af0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,5 @@ -#![crate_name="mml"] -#![crate_type= "lib"] +#![crate_name = "mml"] +#![crate_type = "lib"] #![doc(html_root_url = "https://docs.rs/mml/0.1.41")] @@ -9,72 +9,98 @@ #![cfg_attr(feature = "lints", deny(warnings))] #![cfg_attr(not(any(feature = "lints", feature = "nightly")), deny())] #![deny( - missing_debug_implementations, - missing_copy_implementations, - trivial_casts, - trivial_numeric_casts, - unused_import_braces, - unused_qualifications +missing_debug_implementations, +missing_copy_implementations, +trivial_casts, +trivial_numeric_casts, +unused_import_braces, +unused_qualifications )] //! ![uml](ml.svg) -extern crate syntex_syntax; -extern crate syntex_errors; +extern crate dot; extern crate itertools; +extern crate syn; extern crate walkdir; -extern crate dot; - -pub mod prelude; -pub mod module; -pub mod core; -use std::process::{Command, Stdio}; -use std::io::{self, Write, Read}; -use std::path::Path; -use std::fs::{self, File}; use std::ffi::OsStr; +use std::fs::{self, File}; +use std::io::{self, Read, Write}; +use std::path::Path; +use std::process::{Command, Stdio}; use std::rc::Rc; +use std::result::Result::Err; -use syntex_errors::emitter::ColorConfig; -use syntex_errors::Handler; - -use syntex_syntax::codemap::{CodeMap, FilePathMapping}; -use syntex_syntax::parse::{self, ParseSess}; -use syntex_syntax::{ast, ptr}; - +use syn::parse_file; use walkdir::WalkDir; + use core::ListItem; use module::Module; use module::path::ModulePath; +pub mod prelude; +pub mod module; +pub mod core; + /// The default name of *graph/dot* file. pub const DEFAULT_NAME_DOT: &'static str = "ml.dot"; /// The default name of *image/svg* file. pub const DEFAULT_NAME_PNG: &'static str = "ml.svg"; +#[derive(Debug)] +pub enum Error { + IoError(io::Error), + SynError(syn::Error), +} + +impl std::fmt::Display for Error { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { + let mut debug_struct = f.debug_struct("MlError"); + + match self { + Error::IoError(err) => { debug_struct.field("err", &err.to_string()); } + Error::SynError(err) => { debug_struct.field("err", &err.to_string()); } + } + + debug_struct.finish() + } +} + +impl std::error::Error for Error {} + +impl From for Error { + fn from(err: io::Error) -> Self { + Error::IoError(err) + } +} + +impl From for Error { + fn from(err: syn::Error) -> Self { + Error::SynError(err) + } +} + /// The function `file2crate` returns a syntex module. -fn file2crate>(path: P) -> io::Result { - let codemap = Rc::new(CodeMap::new(FilePathMapping::empty())); - let tty_handler = - Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(codemap.clone())); - let parse_session: ParseSess = ParseSess::with_span_handler(tty_handler, codemap.clone()); - let parse = parse::parse_crate_from_file(path.as_ref(), &parse_session); - let ast: ast::Crate = parse.unwrap(); - - Ok(ast) +fn file2crate>(path: P) -> Result { + let mut content = String::new(); + let _ = File::open(path)?.read_to_string(&mut content)?; + match parse_file(&content) { + Ok(file) => Ok(file), + Err(err) => Err(err.into()), + } } /// The function `items2chars` returns a graph formated for *Graphiz/Dot*. -fn items2chars<'a>(modules: Vec) -> io::Result> { +fn items2chars<'a>(modules: Vec) -> Result, Error> { let mut f: Vec = Vec::new(); - let itt: Vec<(ptr::P, Rc)> = + let iter: Vec<(syn::Item, Rc)> = modules.into_iter() - .flat_map(|s: Module| s.into_iter()) - .collect::, Rc)>>(); - let it: ListItem = ListItem::from(itt.as_slice().into_iter().peekable()); + .flat_map(|s: Module| s.into_iter()) + .collect::)>>(); + let iter: ListItem = ListItem::from(iter.as_slice().into_iter().peekable()); - dot::render(&it, &mut f).and_then(|()| Ok(f)) + dot::render(&iter, &mut f).and_then(|()| Ok(f)).map_err(Into::into) } /// The function `rs2dot` returns graphed file module. @@ -87,8 +113,8 @@ fn items2chars<'a>(modules: Vec) -> io::Result> { /// let _ = mml::rs2dot("src/lib.rs"); /// } /// ``` -pub fn rs2dot<'a, P: AsRef>(path: P) -> io::Result> { - file2crate(path.as_ref()).and_then(|parse: ast::Crate| items2chars(vec![Module::from((parse.module.items, path.as_ref().to_path_buf()))])) +pub fn rs2dot<'a, P: AsRef>(path: P) -> Result, Error> { + file2crate(path.as_ref()).and_then(|parse: syn::File| items2chars(vec![Module::from((parse.items, path.as_ref().to_path_buf()))]).into()) } /// The function `src2dot` returns graphed repository of modules. @@ -101,34 +127,34 @@ pub fn rs2dot<'a, P: AsRef>(path: P) -> io::Result> { /// let _ = mml::src2dot("src"); /// } /// ``` -pub fn src2dot<'a, P: AsRef>(path: P) -> io::Result> { +pub fn src2dot<'a, P: AsRef>(path: P) -> Result, Error> { items2chars(WalkDir::new(path).into_iter() - .filter_map(|entry: Result| entry.ok()) - .filter(|entry| entry.file_type().is_file()) - .filter_map(|entry: walkdir::DirEntry| { - let path: &Path = entry.path(); - - if path.extension().eq(&Some(OsStr::new("rs"))) { - file2crate(path).ok().and_then(|parse| Some(Module::from((parse.module.items, path.to_path_buf())))) - } else { - None - } - }) - .collect::>()) + .filter_map(|entry: Result| entry.ok()) + .filter(|entry| entry.file_type().is_file()) + .filter_map(|entry: walkdir::DirEntry| { + let path: &Path = entry.path(); + + if path.extension().eq(&Some(OsStr::new("rs"))) { + file2crate(path).ok().and_then(|file| Some(Module::from((file.items, path.to_path_buf())))) + } else { + None + } + }) + .collect::>()).map_err(Into::into) } /// The function `content2svg` returns structured vector graphics content of modules. -fn content2svg(buf: Vec) -> io::Result> { +pub fn content2svg(buf: Vec) -> Result, Error> { Command::new("dot").arg("-Tsvg") .stdin(Stdio::piped()).stdout(Stdio::piped()) .spawn() .and_then(|child| { let mut ret = vec![]; - child.stdin.unwrap().write_all(buf.as_slice()).unwrap(); - child.stdout.unwrap().read_to_end(&mut ret).unwrap(); - Ok(ret) - }) + child.stdin.unwrap().write_all(buf.as_slice()).unwrap(); + child.stdout.unwrap().read_to_end(&mut ret).unwrap(); + Ok(ret) + }).map_err(Into::into) } /// The function `rs2svg` returns structured vector graphics file modules. @@ -141,8 +167,8 @@ fn content2svg(buf: Vec) -> io::Result> { /// let _ = mml::rs2svg("src/lib.rs"); /// } /// ``` -pub fn rs2svg>(path: P) -> io::Result> { - rs2dot(path).and_then(|buf| content2svg(buf)) +pub fn rs2svg>(path: P) -> Result, Error> { + rs2dot(path).and_then(|buf| content2svg(buf).map_err(Into::into)) } /// The function `src2svg` returns structured vector graphics repository of modules. @@ -155,8 +181,8 @@ pub fn rs2svg>(path: P) -> io::Result> { /// let _ = mml::src2svg("src"); /// } /// ``` -pub fn src2svg>(path: P) -> io::Result> { - src2dot(path).and_then(|buf| content2svg(buf)) +pub fn src2svg>(path: P) -> Result, Error> { + src2dot(path).and_then(|buf| content2svg(buf).map_err(Into::into)) } /// The function `src2both` creates two files formated like a graph/dot and a structured vector graphics. @@ -171,7 +197,7 @@ pub fn src2svg>(path: P) -> io::Result> { /// let _ = mml::src2both("src", dest.replace("-", "_").as_str()); /// } /// ``` -pub fn src2both>(src: P, dest: P) -> io::Result<()> { +pub fn src2both>(src: P, dest: P) -> Result<(), Error> { let _ = fs::create_dir_all(dest.as_ref())?; let mut file_dot = File::create(dest.as_ref().join(DEFAULT_NAME_DOT))?; let mut file_svg = File::create(dest.as_ref().join(DEFAULT_NAME_PNG))?; diff --git a/src/module/mod.rs b/src/module/mod.rs index 77df6312..ff8d5edd 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -3,20 +3,20 @@ use std::path::PathBuf; use std::ffi::OsString; use std::vec; -use syntex_syntax::{ast, ptr}; - +extern crate syn; pub mod path; use self::path::ModulePath; +use syn::Item; #[derive(Default, Debug, Clone)] pub struct Module { - pub list: Vec>, + pub list: Vec, pub path: ModulePath, } -impl From<(Vec>, PathBuf)> for Module { - fn from((list, mut path): (Vec>, PathBuf)) -> Module { +impl From<(Vec, PathBuf)> for Module { + fn from((list, mut path): (Vec, PathBuf)) -> Module { path.set_extension(""); Module { list: list, @@ -31,14 +31,14 @@ impl From<(Vec>, PathBuf)> for Module { } impl IntoIterator for Module { - type Item = (ptr::P, Rc); - type IntoIter = vec::IntoIter<(ptr::P, Rc)>; + type Item = (Item, Rc); + type IntoIter = vec::IntoIter<(Item, Rc)>; fn into_iter(self) -> Self::IntoIter { let ref rc: Rc = Rc::new(self.path); self.list.into_iter() .map(|item| (item, Rc::clone(rc))) - .collect::, Rc)>>() + .collect::)>>() .into_iter() } } diff --git a/tests/aggregation.rs b/tests/aggregation.rs index 14eb5728..a9cfa35f 100644 --- a/tests/aggregation.rs +++ b/tests/aggregation.rs @@ -17,8 +17,8 @@ fn test_aggregation() { assert_eq!( String::from_utf8(mml::rs2dot("tests/aggregation.rs").unwrap()).unwrap(), r#"digraph ml { - ndAmut[label="{<<<Structure>>>\nAmut|- b: *mut B}"][shape="record"]; - ndAconst[label="{<<<Structure>>>\nAconst|- b: *const B}"][shape="record"]; + ndAmut[label="{<<<Structure>>>\nAmut|- b: * mut B}"][shape="record"]; + ndAconst[label="{<<<Structure>>>\nAconst|- b: * const B}"][shape="record"]; ndB[label="{<<<Structure>>>\nB}"][shape="record"]; ndB -> ndAmut[label=""][arrowhead="odiamond"]; ndB -> ndAconst[label=""][arrowhead="odiamond"]; diff --git a/tests/dependency.rs b/tests/dependency.rs index c74620e9..0f1fdad9 100644 --- a/tests/dependency.rs +++ b/tests/dependency.rs @@ -17,7 +17,7 @@ fn test_dependency() { assert_eq!( String::from_utf8(mml::rs2dot("tests/dependency.rs").unwrap()).unwrap(), r#"digraph ml { - ndA[label="{<<<Structure>>>\nA|- b(b: &B)}"][shape="record"]; + ndA[label="{<<<Structure>>>\nA|- b(b : & B)}"][shape="record"]; ndB[label="{<<<Structure>>>\nB}"][shape="record"]; ndB -> ndA[label=""][style="dashed"][arrowhead="vee"]; } diff --git a/tests/realization.rs b/tests/realization.rs index 4c58ee0c..3fa917ac 100644 --- a/tests/realization.rs +++ b/tests/realization.rs @@ -36,8 +36,8 @@ impl B { fn test_realization() { assert_eq!(String::from_utf8(mml::rs2dot("tests/realization.rs").unwrap()).unwrap(), r#"digraph ml { - ndA[label="{<<<Structure>>>\nA|- a: T|- a(a: T) -> Self}"][shape="record"]; - ndB[label="{<<<Trait>>>\nB|a(&Self) -> Option<T>|- a(&self) -> Option<T>}"][shape="record"]; + ndA[label="{<<<Structure>>>\nA|- a: T|- a(a : T) -> Self}"][shape="record"]; + ndB[label="{<<<Trait>>>\nB|a(& Self) -> Option < T >|- a(& self) -> Option < T >}"][shape="record"]; ndB -> ndA[label=""][style="dashed"][arrowhead="onormal"]; } "#); From ac98097dedf4e747e2aad856bbad105e03c08b03 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Tue, 3 Mar 2020 20:33:13 +0100 Subject: [PATCH 02/11] Remove doc upload for CI --- .travis.yml | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/.travis.yml b/.travis.yml index 57648ee4..98241835 100644 --- a/.travis.yml +++ b/.travis.yml @@ -28,12 +28,4 @@ script: travis-cargo run travis-cargo test travis-cargo bench - travis-cargo doc -- --no-deps -after_success: - - touch target/doc/index.html - - travis-cargo --only nightly doc-upload - - travis-cargo coveralls --no-sudo --verify -env: - global: - - TRAVIS_CARGO_NIGHTLY_FEATURE="nightly" - - secure: "DKEIK2vaRCzWGkEv6fpPhkmszMQBD0lTP5PeNBQ4C6vtRWAGtHdqYxFuXtCIwE264tFYj9zoSZo9Bz+fWCOgvX2nQZwX6MRnMB+jaG+8jo0GynQs8L3Ldwj0MgJJ19+teEa5sR3IGZL94BGbG4bMPoUepTJRrGVXMXry38VFLUjLVBSB3pim7ivc2CWr++Y7s5Rdzrf26IrfjSSHHewW/acNZnSsdrivVt6VfziYVJFEEs6VSmR7Camgoc0VNjQLEP2fMYbnbMuQJ+ftQTYpdbdCoH2R+e3VFMLCpdIccE8RycA2mX1KRJXJSGXmtAhQ30brx1IoStHjtLct0NSQd86SVSjRlkDmyG6hGxehWA1V06HnUSLlJMw0hZT07jVpewmjcWfZAWm5Vg/jeC3qWLo/anVpTiH80CUukkCUZyXkKC6ePFfb84Cf8dgdEvxchUKIH6T6Q+/yePkmn2tKepXadgNgHpoJ6Yp89jJl1e+lEFgh1hw2Wy1rsAgwbKFwZ3/fGz6pDqm+vhfelmQhLHKdwERFIoFOhSjizjajD1CbHO+aZQjznguYO34x/MZ70ZyVB2MiIkn4ujsZ6U41KCS51QQa1XIZOVlNmcMx+GmZLg8eC/H/pwSKaM4LS4websJMjwhRw7EU227YzfefSW6krtushgrWa9s8pVacYT8=" + travis-cargo doc -- --no-deps \ No newline at end of file From 59f162d88903c2da0464365ffaed6ed972189cd3 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Tue, 3 Mar 2020 21:25:32 +0100 Subject: [PATCH 03/11] Add svg image generation to tests --- tests/aggregation.rs | 26 ++++++++++++++++++++------ tests/association.rs | 41 +++++++++++++++++++++++++---------------- tests/composition.rs | 26 ++++++++++++++++++++------ tests/dependency.rs | 32 ++++++++++++++++++++++---------- tests/realization.rs | 27 +++++++++++++++++++++------ 5 files changed, 108 insertions(+), 44 deletions(-) diff --git a/tests/aggregation.rs b/tests/aggregation.rs index a9cfa35f..20459055 100644 --- a/tests/aggregation.rs +++ b/tests/aggregation.rs @@ -1,6 +1,10 @@ #![allow(dead_code)] extern crate mml; +use std::fs::File; +use std::io::Write; +use std::path::Path; + struct Amut { b: *mut B, } @@ -9,19 +13,29 @@ struct Aconst { b: *const B, } -struct B { -} +struct B {} #[test] fn test_aggregation() { - assert_eq!( - String::from_utf8(mml::rs2dot("tests/aggregation.rs").unwrap()).unwrap(), - r#"digraph ml { + let vec = mml::rs2dot("tests/aggregation.rs").unwrap(); + let target = r#"digraph ml { ndAmut[label="{<<<Structure>>>\nAmut|- b: * mut B}"][shape="record"]; ndAconst[label="{<<<Structure>>>\nAconst|- b: * const B}"][shape="record"]; ndB[label="{<<<Structure>>>\nB}"][shape="record"]; ndB -> ndAmut[label=""][arrowhead="odiamond"]; ndB -> ndAconst[label=""][arrowhead="odiamond"]; } -"#); +"#; + + let path = "target/test/aggregation"; + if let Err(_) = std::fs::create_dir_all(path) { + if !Path::new(path).is_dir() { + panic!("Could not create directory!") + } + } + + File::create("target/test/aggregation/aggregation.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); + File::create("target/test/aggregation/aggregation_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + + assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/association.rs b/tests/association.rs index 7f69b13d..120bc804 100644 --- a/tests/association.rs +++ b/tests/association.rs @@ -1,46 +1,55 @@ #![allow(dead_code)] extern crate mml; -struct A { -} +use std::path::Path; +use std::fs::File; +use std::io::Write; + +struct A {} impl A { fn b() -> B { - B { - } + B {} } } -struct Ab { -} +struct Ab {} impl Ab { fn b() -> B { - B { - } + B {} } } -struct B { -} +struct B {} impl B { fn a() -> Ab { - Ab { - } + Ab {} } } #[test] fn test_association() { - assert_eq!( - String::from_utf8(mml::rs2dot("tests/association.rs").unwrap()).unwrap(), - r#"digraph ml { + let vec = mml::rs2dot("tests/association.rs").unwrap(); + let target = r#"digraph ml { ndA[label="{<<<Structure>>>\nA|- b() -> B}"][shape="record"]; ndAb[label="{<<<Structure>>>\nAb|- b() -> B}"][shape="record"]; ndB[label="{<<<Structure>>>\nB|- a() -> Ab}"][shape="record"]; ndAb -> ndB[label=""][arrowhead="none"]; ndB -> ndA[label=""][arrowhead="vee"]; } -"#); +"#; + + let path = "target/test/association"; + if let Err(_) = std::fs::create_dir_all(path) { + if !Path::new(path).is_dir() { + panic!("Could not create directory!") + } + } + + File::create("target/test/association/association.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); + File::create("target/test/association/association_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + + assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/composition.rs b/tests/composition.rs index e3873959..2b10ac9b 100644 --- a/tests/composition.rs +++ b/tests/composition.rs @@ -2,21 +2,35 @@ extern crate mml; +use std::fs::File; +use std::io::Write; +use std::path::Path; + struct A { b: B, } -struct B { -} +struct B {} #[test] fn test_composition() { - assert_eq!( - String::from_utf8(mml::rs2dot("tests/composition.rs").unwrap()).unwrap(), - r#"digraph ml { + let vec = mml::rs2dot("tests/composition.rs").unwrap(); + let target = r#"digraph ml { ndA[label="{<<<Structure>>>\nA|- b: B}"][shape="record"]; ndB[label="{<<<Structure>>>\nB}"][shape="record"]; ndB -> ndA[label=""][arrowhead="diamond"]; } -"#); +"#; + + let path = "target/test/composition/"; + if let Err(_) = std::fs::create_dir_all(path) { + if !Path::new(path).is_dir() { + panic!("Could not create directory!") + } + } + + File::create("target/test/composition/composition.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); + File::create("target/test/composition/composition_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + + assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/dependency.rs b/tests/dependency.rs index 0f1fdad9..9bb8a774 100644 --- a/tests/dependency.rs +++ b/tests/dependency.rs @@ -1,25 +1,37 @@ #![allow(dead_code, unused_variables)] extern crate mml; -struct A { -} +use std::fs::File; +use std::path::Path; +use std::io::Write; + +struct A {} impl A { - fn b(b: &B) { - } + fn b(b: &B) {} } -struct B { -} +struct B {} #[test] fn test_dependency() { - assert_eq!( - String::from_utf8(mml::rs2dot("tests/dependency.rs").unwrap()).unwrap(), - r#"digraph ml { + let vec = mml::rs2dot("tests/dependency.rs").unwrap(); + let target = r#"digraph ml { ndA[label="{<<<Structure>>>\nA|- b(b : & B)}"][shape="record"]; ndB[label="{<<<Structure>>>\nB}"][shape="record"]; ndB -> ndA[label=""][style="dashed"][arrowhead="vee"]; } -"#); +"#; + + let path = "target/test/dependency"; + if let Err(_) = std::fs::create_dir_all(path) { + if !Path::new(path).is_dir() { + panic!("Could not create directory!") + } + } + + File::create("target/test/dependency/dependency.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); + File::create("target/test/dependency/dependency_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + + assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/realization.rs b/tests/realization.rs index 3fa917ac..bdc61b26 100644 --- a/tests/realization.rs +++ b/tests/realization.rs @@ -2,6 +2,9 @@ extern crate mml; use std::fmt::Debug; +use std::fs::File; +use std::io::Write; +use std::path::Path; #[derive(Debug)] struct A where T: Debug { @@ -16,17 +19,17 @@ impl A where T: Debug { } } -impl B for A where T: Debug { +impl B for A where T: Debug { fn a(&self) -> Option { None } } -trait B : Debug where T: Debug { +trait B: Debug where T: Debug { fn a(&self) -> Option; } -impl B { +impl B { fn a(&self) -> Option { None } @@ -34,11 +37,23 @@ impl B { #[test] fn test_realization() { - assert_eq!(String::from_utf8(mml::rs2dot("tests/realization.rs").unwrap()).unwrap(), - r#"digraph ml { + let vec = mml::rs2dot("tests/realization.rs").unwrap(); + let target = r#"digraph ml { ndA[label="{<<<Structure>>>\nA|- a: T|- a(a : T) -> Self}"][shape="record"]; ndB[label="{<<<Trait>>>\nB|a(& Self) -> Option < T >|- a(& self) -> Option < T >}"][shape="record"]; ndB -> ndA[label=""][style="dashed"][arrowhead="onormal"]; } -"#); +"#; + + let path = "target/test/realization"; + if let Err(_) = std::fs::create_dir_all(path) { + if !Path::new(path).is_dir() { + panic!("Could not create directory!") + } + } + + File::create("target/test/realization/realization.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); + File::create("target/test/realization/realization_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + + assert_eq!(String::from_utf8(vec).unwrap(), target); } From f8490f84761cd3c28d7e70263e166fa3f07519fc Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Fri, 29 Jan 2021 22:25:53 +0100 Subject: [PATCH 04/11] Remove explicitly added bin target --- Cargo.toml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 029d9473..379761fd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,11 +17,6 @@ categories = ["visualization"] travis-ci = { repository = "adjivas/ml", branch = "master" } appveyor = { repository = "adjivas/ml", branch = "master", service = "github" } -[[bin]] -name = "ml" -doc = false -test = false - [lib] test = false doctest = true From 3dabf184ca7c9e30cadb4bebc1302d17165627b7 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Sat, 30 Jan 2021 14:58:07 +0100 Subject: [PATCH 05/11] Update quote and syn --- Cargo.toml | 4 ++-- src/core/item/state/abstraction/enumerate.rs | 2 +- src/core/item/state/abstraction/extend.rs | 2 +- src/core/item/state/abstraction/structure.rs | 2 +- src/core/item/state/implem.rs | 2 +- src/core/item/state/method.rs | 2 +- src/lib.rs | 1 + 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 379761fd..4f0d5ba6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,8 +32,8 @@ debug = [] # for building with debug messages travis = ["lints", "nightly"] # for building with travis-cargo [dependencies] -syn = { features = [ "full", "default", "extra-traits", "derive", "parsing", "printing", "clone-impls", "proc-macro" ], version = "1.0.14" } -quote = "1.0.2" +syn = { features = [ "full", "default", "extra-traits", "derive", "parsing", "printing", "clone-impls", "proc-macro" ], version = "1.0" } +quote = "1.0" [dependencies.rustc-serialize] version = "0.3" diff --git a/src/core/item/state/abstraction/enumerate.rs b/src/core/item/state/abstraction/enumerate.rs index 3fe9aa44..5201601e 100644 --- a/src/core/item/state/abstraction/enumerate.rs +++ b/src/core/item/state/abstraction/enumerate.rs @@ -2,8 +2,8 @@ use std::fmt; use std::rc::Rc; use ::dot::escape_html; +use quote::{TokenStreamExt, ToTokens}; use syn::{Field, TypeParam, Variant}; -use syn::export::ToTokens; use ::module::path::ModulePath; diff --git a/src/core/item/state/abstraction/extend.rs b/src/core/item/state/abstraction/extend.rs index 2ef943cb..80663317 100644 --- a/src/core/item/state/abstraction/extend.rs +++ b/src/core/item/state/abstraction/extend.rs @@ -2,8 +2,8 @@ use std::fmt; use std::rc::Rc; use ::dot::escape_html; +use quote::{TokenStreamExt, ToTokens}; use syn::{FnArg, ItemTrait, PatType, Receiver, ReturnType, Signature, TraitItem, TraitItemMethod, TypeParam, Visibility}; -use syn::export::ToTokens; use ::module::path::ModulePath; diff --git a/src/core/item/state/abstraction/structure.rs b/src/core/item/state/abstraction/structure.rs index 6e67d546..18acf9f4 100644 --- a/src/core/item/state/abstraction/structure.rs +++ b/src/core/item/state/abstraction/structure.rs @@ -4,7 +4,7 @@ use std::rc::Rc; use ::dot::escape_html; use syn::{Field, ItemStruct, Visibility}; -use syn::export::ToTokens; +use quote::{ToTokens, TokenStreamExt}; use ::module::path::ModulePath; diff --git a/src/core/item/state/implem.rs b/src/core/item/state/implem.rs index 11166db3..121fa9a2 100644 --- a/src/core/item/state/implem.rs +++ b/src/core/item/state/implem.rs @@ -1,8 +1,8 @@ use std::fmt; use ::dot::escape_html; +use quote::{TokenStreamExt, ToTokens}; use syn::{AngleBracketedGenericArguments, FnArg, GenericArgument, ImplItem, ImplItemMethod, PathArguments, PathSegment, ReturnType, Signature}; -use syn::export::ToTokens; use syn::punctuated::Punctuated; use syn::token::Colon2; diff --git a/src/core/item/state/method.rs b/src/core/item/state/method.rs index 3bc65faa..8c22447c 100644 --- a/src/core/item/state/method.rs +++ b/src/core/item/state/method.rs @@ -2,8 +2,8 @@ use std::fmt; use std::rc::Rc; use ::dot::escape_html; +use quote::{TokenStreamExt, ToTokens}; use syn::{ - export::ToTokens, FnArg, ImplItem, ImplItemMethod, diff --git a/src/lib.rs b/src/lib.rs index d2638af0..a2165352 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,6 +23,7 @@ extern crate dot; extern crate itertools; extern crate syn; extern crate walkdir; +extern crate quote; use std::ffi::OsStr; use std::fs::{self, File}; From 83da1533b9d94c2cfde06d4da7ee08fc52be28e3 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Sat, 30 Jan 2021 15:19:33 +0100 Subject: [PATCH 06/11] Fix clippy lints --- src/core/item/state/abstraction/enumerate.rs | 2 +- src/core/item/state/abstraction/extend.rs | 7 ++----- src/core/item/state/abstraction/structure.rs | 2 +- src/core/item/state/implem.rs | 6 +++--- src/core/item/state/method.rs | 6 +++--- src/core/item/state/mod.rs | 18 +++++++++++------- src/module/mod.rs | 2 +- tests/realization.rs | 4 ++-- 8 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/core/item/state/abstraction/enumerate.rs b/src/core/item/state/abstraction/enumerate.rs index 5201601e..1a3c2604 100644 --- a/src/core/item/state/abstraction/enumerate.rs +++ b/src/core/item/state/abstraction/enumerate.rs @@ -2,7 +2,7 @@ use std::fmt; use std::rc::Rc; use ::dot::escape_html; -use quote::{TokenStreamExt, ToTokens}; +use quote::ToTokens; use syn::{Field, TypeParam, Variant}; use ::module::path::ModulePath; diff --git a/src/core/item/state/abstraction/extend.rs b/src/core/item/state/abstraction/extend.rs index 80663317..4cfa251f 100644 --- a/src/core/item/state/abstraction/extend.rs +++ b/src/core/item/state/abstraction/extend.rs @@ -2,7 +2,7 @@ use std::fmt; use std::rc::Rc; use ::dot::escape_html; -use quote::{TokenStreamExt, ToTokens}; +use quote::ToTokens; use syn::{FnArg, ItemTrait, PatType, Receiver, ReturnType, Signature, TraitItem, TraitItemMethod, TypeParam, Visibility}; use ::module::path::ModulePath; @@ -42,10 +42,7 @@ impl<'a> From<((&'a ItemTrait, &'a Vec, &'a Vec), Rc { - None + Some([r1, r2, mutability, s].iter().flatten().map(ToString::to_string).collect()) } } }).collect(), output.to_token_stream().to_string())) diff --git a/src/core/item/state/abstraction/structure.rs b/src/core/item/state/abstraction/structure.rs index 18acf9f4..69eb8f6f 100644 --- a/src/core/item/state/abstraction/structure.rs +++ b/src/core/item/state/abstraction/structure.rs @@ -3,8 +3,8 @@ use std::fmt::{Debug, Formatter}; use std::rc::Rc; use ::dot::escape_html; +use quote::ToTokens; use syn::{Field, ItemStruct, Visibility}; -use quote::{ToTokens, TokenStreamExt}; use ::module::path::ModulePath; diff --git a/src/core/item/state/implem.rs b/src/core/item/state/implem.rs index 121fa9a2..7c0e7f43 100644 --- a/src/core/item/state/implem.rs +++ b/src/core/item/state/implem.rs @@ -1,7 +1,7 @@ use std::fmt; use ::dot::escape_html; -use quote::{TokenStreamExt, ToTokens}; +use quote::ToTokens; use syn::{AngleBracketedGenericArguments, FnArg, GenericArgument, ImplItem, ImplItemMethod, PathArguments, PathSegment, ReturnType, Signature}; use syn::punctuated::Punctuated; use syn::token::Colon2; @@ -48,8 +48,8 @@ impl Implem { impl From<(Vec<(String, Vec)>, Vec<(String, Vec, Option)>)> for Implem { fn from((ty, method): (Vec<(String, Vec)>, Vec<(String, Vec, Option)>)) -> Implem { Implem { - ty: ty, - method: method, + ty, + method, } } } diff --git a/src/core/item/state/method.rs b/src/core/item/state/method.rs index 8c22447c..0f2e61ac 100644 --- a/src/core/item/state/method.rs +++ b/src/core/item/state/method.rs @@ -2,7 +2,7 @@ use std::fmt; use std::rc::Rc; use ::dot::escape_html; -use quote::{TokenStreamExt, ToTokens}; +use quote::ToTokens; use syn::{ FnArg, ImplItem, @@ -59,8 +59,8 @@ impl<'a> Method<'a> { impl<'a> From<(Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, Rc)> for Method<'a> { fn from((func, path): (Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, Rc)) -> Method<'a> { Method { - func: func, - path: path, + func, + path, } } } diff --git a/src/core/item/state/mod.rs b/src/core/item/state/mod.rs index 19fc4d3d..933be888 100644 --- a/src/core/item/state/mod.rs +++ b/src/core/item/state/mod.rs @@ -127,10 +127,14 @@ impl<'a> From<(Abstract<'a>, Vec<&'a (Item, Rc)>)> for ItemState<'a> node, method: properties.iter() .filter_map(|&&(ref item, ref path): &&'a (Item, Rc)| - if let Item::Impl(ItemImpl { trait_: None, items, .. }) = item { - Some(Method::from((items, Rc::clone(path)))) - } else { - None + match item { + Item::Impl(ItemImpl { trait_, items, .. }) + if trait_.is_none() => { + Some(Method::from((items, Rc::clone(path)))) + } + _ => { + None + } } ) .collect(), @@ -151,7 +155,7 @@ impl<'a> From)>> for ItemState<'a> { fn from(state: Vec<&'a (Item, Rc)>) -> ItemState<'a> { state.split_first().and_then(|(&&(ref item, ref path), properties): (&&'a (Item, Rc), &[&'a (Item, Rc)])| { match &item { - /// Trait. + // Trait. &Item::Trait(item) => { let ItemTrait { generics, items, .. } = item; let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME @@ -159,14 +163,14 @@ impl<'a> From)>> for ItemState<'a> { let kind: (Abstract, Vec<&'a (Item, Rc)>) = (Abstract::Trait((kind, Rc::clone(path)).into()), properties.to_vec()); Some(ItemState::from(kind)) } - /// Structure with variables. + // Structure with variables. &Item::Struct(item) => { let fields = Box::leak(Box::new(item.fields.iter().cloned().collect())); // FIXME let kind: (_, &Vec) = (item, fields); let kind = (Abstract::Struct((kind, Rc::clone(path)).into()), properties.to_vec()); Some(ItemState::from(kind)) } - /// Enumeration with variables. + // Enumeration with variables. &Item::Enum(item) => { let ItemEnum { generics, variants, .. } = item; let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME diff --git a/src/module/mod.rs b/src/module/mod.rs index ff8d5edd..bd386c66 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -19,7 +19,7 @@ impl From<(Vec, PathBuf)> for Module { fn from((list, mut path): (Vec, PathBuf)) -> Module { path.set_extension(""); Module { - list: list, + list, path: ModulePath { path: path.components() .skip(1) diff --git a/tests/realization.rs b/tests/realization.rs index bdc61b26..1f671133 100644 --- a/tests/realization.rs +++ b/tests/realization.rs @@ -14,7 +14,7 @@ struct A where T: Debug { impl A where T: Debug { fn a(a: T) -> Self { A { - a: a, + a, } } } @@ -29,7 +29,7 @@ trait B: Debug where T: Debug { fn a(&self) -> Option; } -impl B { +impl dyn B { fn a(&self) -> Option { None } From 587acf0589e5b3b2f198c3b1b636651c476aab3b Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Sat, 30 Jan 2021 15:28:47 +0100 Subject: [PATCH 07/11] Fix clippy lints --- src/core/item/state/abstraction/enumerate.rs | 4 ++-- src/core/item/state/abstraction/extend.rs | 6 +++--- src/core/item/state/implem.rs | 12 ++++++------ src/core/item/state/mod.rs | 12 ++++-------- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/core/item/state/abstraction/enumerate.rs b/src/core/item/state/abstraction/enumerate.rs index 1a3c2604..d4612f0d 100644 --- a/src/core/item/state/abstraction/enumerate.rs +++ b/src/core/item/state/abstraction/enumerate.rs @@ -50,9 +50,9 @@ impl<'a> fmt::Display for Enum<'a> { write!(f, "<<<Enumeration>>>\n{name}|{variants}", name = self.name, variants = escape_html(self.variants.iter() - .map(|&(ref name, ref struct_field): &(String, Vec)| + .map(|( name, struct_field)| if struct_field.is_empty() { - format!("{}", name) + name.to_owned() } else { format!("{}({})", name, struct_field.join(", ")) } diff --git a/src/core/item/state/abstraction/extend.rs b/src/core/item/state/abstraction/extend.rs index 4cfa251f..a34c6bb3 100644 --- a/src/core/item/state/abstraction/extend.rs +++ b/src/core/item/state/abstraction/extend.rs @@ -29,11 +29,11 @@ impl<'a> From<((&'a ItemTrait, &'a Vec, &'a Vec), Rc { - Some(ty.to_token_stream().to_string()) + ty.to_token_stream().to_string() } FnArg::Receiver(Receiver { reference, mutability, .. }) => { // FIXME let (r1, r2) = match reference { @@ -42,7 +42,7 @@ impl<'a> From<((&'a ItemTrait, &'a Vec, &'a Vec), Rc bool { + pub fn is_realization(&self, ty_name: &str) -> bool { if let Some(&(ref name, _)) = self.ty.first() { name.to_string().eq(ty_name) } else { @@ -25,10 +25,10 @@ impl Implem { } } - pub fn is_association(&self, ty_name: &String) -> bool { + pub fn is_association(&self, ty_name: &str) -> bool { self.method.iter() - .any(|&(_, _, ref result): &(String, Vec, Option)| - if let &Some(ref ret) = result { + .any(|(_, _, result)| + if let Some(ret) = result { ret.split(|at| "<[(;, )]>".contains(at)) .any(|ty| ty.eq(ty_name)) } else { @@ -37,7 +37,7 @@ impl Implem { ) } - pub fn is_dependency(&self, _: &String) -> bool { + pub fn is_dependency(&self, _: &str) -> bool { false /*self.method.iter() .any(|&( _, ref arg, _): &(String, Vec, Option)| @@ -100,7 +100,7 @@ impl fmt::Display for Implem { write!(f, "{item}", item = escape_html(self.method.iter() .map(|&(ref name, ref args, ref result): &(String, Vec, Option)| { - if let &Some(ref ret) = result { + if let Some(ret) = result { format!("{}{}({}) -> {}", DEFAULT_FUNC, name, args.join(", "), ret) } else { format!("{}{}({})", DEFAULT_FUNC, name, args.join(", ")) diff --git a/src/core/item/state/mod.rs b/src/core/item/state/mod.rs index 933be888..4b655fbc 100644 --- a/src/core/item/state/mod.rs +++ b/src/core/item/state/mod.rs @@ -126,20 +126,16 @@ impl<'a> From<(Abstract<'a>, Vec<&'a (Item, Rc)>)> for ItemState<'a> ItemState { node, method: properties.iter() - .filter_map(|&&(ref item, ref path): &&'a (Item, Rc)| + .filter_map(|(item, path)| match item { Item::Impl(ItemImpl { trait_, items, .. }) - if trait_.is_none() => { - Some(Method::from((items, Rc::clone(path)))) - } - _ => { - None - } + if trait_.is_none() => Some(Method::from((items, Rc::clone(path)))), + _ => None, } ) .collect(), implem: properties.iter() - .filter_map(|&&(ref item, _): &&'a (Item, Rc)| + .filter_map(|(item, _)| if let Item::Impl(ItemImpl { trait_: Some((_, Path { segments, .. }, _)), items, .. }) = item { Some(Implem::from((segments, items))) } else { From f3e0be88a2876abe69ac0d9d1674e0e73ca2e0ee Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Sat, 30 Jan 2021 15:38:24 +0100 Subject: [PATCH 08/11] Fix clippy lints --- src/core/item/mod.rs | 34 ++++++++++++-------------- src/core/item/relation.rs | 16 ++++++------ src/core/item/state/abstraction/mod.rs | 3 +-- src/core/item/state/method.rs | 10 ++++---- src/core/item/state/mod.rs | 14 ++++------- src/core/mod.rs | 8 +++--- src/module/mod.rs | 2 +- 7 files changed, 39 insertions(+), 48 deletions(-) diff --git a/src/core/item/mod.rs b/src/core/item/mod.rs index 4546a2f8..47466546 100644 --- a/src/core/item/mod.rs +++ b/src/core/item/mod.rs @@ -1,25 +1,23 @@ -pub mod relation; -pub mod state; - -pub use self::state::ItemState; - -use std::{slice, iter}; +use std::{iter, slice}; use std::rc::Rc; use ::itertools::Itertools; use ::module::path::ModulePath; -/// The structure Item is a iterable collection of abstract elements. +pub use self::state::ItemState; + +pub mod relation; +pub mod state; +/// The structure Item is a iterable collection of abstract elements. #[derive(Debug, Clone)] -pub struct Item <'a> { +pub struct Item<'a> { /// Iterator. it: iter::Peekable)>>, } -impl <'a>From)>>> for Item<'a> { - +impl<'a> From)>>> for Item<'a> { /// The constructor method `from` returns a typed and iterable collection of abstract element. fn from(iter: iter::Peekable)>>) -> Item { Item { @@ -28,7 +26,7 @@ impl <'a>From)>>> for } } -impl <'a>Iterator for Item<'a> { +impl<'a> Iterator for Item<'a> { type Item = ItemState<'a>; /// The method `next` will returns the first abstract elements defined like a structure, @@ -37,14 +35,12 @@ impl <'a>Iterator for Item<'a> { self.it.next().and_then(|item| { let mut list: Vec<&'a (syn::Item, Rc)> = vec!(item); - list.extend(self.it.peeking_take_while(|&&(ref item, _): &&'a (syn::Item, Rc)| { - if let syn::Item::Impl(_) = item { - true - } else { - false - } - }) - .collect::)>>()); + list.extend(self.it.peeking_take_while(|(item, _)| + if let syn::Item::Impl(_) = item { + true + } else { + false + })); Some(ItemState::from(list)) }) } diff --git a/src/core/item/relation.rs b/src/core/item/relation.rs index 6cdb1a8f..6f9a2b54 100644 --- a/src/core/item/relation.rs +++ b/src/core/item/relation.rs @@ -1,6 +1,6 @@ -use super::ItemState; +use ::dot::{ArrowShape, Fill, Side}; -use ::dot::{Fill, ArrowShape, Side}; +use super::ItemState; /// The enumeration `Relation` is the relationship specification from [UML 2.5](http://www.omg.org/spec/UML/2.5) without generalization. #[derive(Debug, Copy, Clone)] @@ -18,12 +18,12 @@ impl Relation { /// The method `as_style` returns a stylized arrow (See *Table B.2 UML Edges* from [UML 2.5](http://www.omg.org/spec/UML/2.5). pub fn as_style(&self) -> ArrowShape { match self { - &Relation::Association => ArrowShape::Vee(Side::Both), - &Relation::Dependency => ArrowShape::Vee(Side::Both), - &Relation::Aggregation => ArrowShape::Diamond(Fill::Open, Side::Both), - &Relation::Composition => ArrowShape::Diamond(Fill::Filled, Side::Both), - &Relation::Realization => ArrowShape::Normal(Fill::Open, Side::Both), - &Relation::None => ArrowShape::NoArrow, + Relation::Association => ArrowShape::Vee(Side::Both), + Relation::Dependency => ArrowShape::Vee(Side::Both), + Relation::Aggregation => ArrowShape::Diamond(Fill::Open, Side::Both), + Relation::Composition => ArrowShape::Diamond(Fill::Filled, Side::Both), + Relation::Realization => ArrowShape::Normal(Fill::Open, Side::Both), + Relation::None => ArrowShape::NoArrow, } } } diff --git a/src/core/item/state/abstraction/mod.rs b/src/core/item/state/abstraction/mod.rs index dbac54ad..ee573d2a 100644 --- a/src/core/item/state/abstraction/mod.rs +++ b/src/core/item/state/abstraction/mod.rs @@ -47,9 +47,8 @@ impl<'a> IntoIterator for &'a Abstract<'a> { } Abstract::Enum(Enum { variants, .. }) => { variants.iter() - .map(|&(_, ref ty_field): &'a (String, Vec)| + .map(|(_, ty_field)| ty_field.iter() - .map(|ty: &'a String| ty) .collect::>()) .collect::>>() .concat() diff --git a/src/core/item/state/method.rs b/src/core/item/state/method.rs index 0f2e61ac..3984d7a9 100644 --- a/src/core/item/state/method.rs +++ b/src/core/item/state/method.rs @@ -28,10 +28,10 @@ pub struct Method<'a> { } impl<'a> Method<'a> { - pub fn is_association(&self, ty_name: &String) -> bool { + pub fn is_association(&self, ty_name: &str) -> bool { self.func.iter() - .any(|&(_, _, _, ref result)| - if let &Some(ret) = result { + .any(|(_, _, _, result)| + if let Some(ret) = result { // TODO: replace by checking if ret (which is of type Type) // TODO: contains ty_name anywhere ret.to_token_stream().to_string().split(|at| "<[(;, )]>".contains(at)) @@ -42,9 +42,9 @@ impl<'a> Method<'a> { ) } - pub fn is_dependency(&self, name: &String) -> bool { + pub fn is_dependency(&self, name: &str) -> bool { self.func.iter() - .any(|&(_, _, ref arg, _): &(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)| + .any(|(_, _, arg, _)| arg.iter().filter_map(|ty| { if let FnArg::Typed(ty) = ty { Some(ty) diff --git a/src/core/item/state/mod.rs b/src/core/item/state/mod.rs index 4b655fbc..b5e6a0bf 100644 --- a/src/core/item/state/mod.rs +++ b/src/core/item/state/mod.rs @@ -39,26 +39,22 @@ impl<'a> ItemState<'a> { } pub fn is_association(&self, rhs: &ItemState<'a>) -> bool { - if let Some(ref name) = self.as_name() { - let ref ty_name: String = name.to_string(); - + if let Some(ty_name) = self.as_name() { rhs.method.iter() .any(|func| func.is_association(ty_name)) .bitor(rhs.implem.iter() - .any(|implem| implem.is_association(&ty_name))) + .any(|implem| implem.is_association(ty_name))) } else { false } } pub fn is_dependency(&self, rhs: &ItemState<'a>) -> bool { - if let Some(ref name) = self.as_name() { - let ref ty_name: String = name.to_string(); - + if let Some(ty_name) = self.as_name() { rhs.method.iter() - .any(|method| method.is_dependency(&ty_name)) + .any(|method| method.is_dependency(ty_name)) .bitor(self.implem.iter() - .any(|implem| implem.is_dependency(&ty_name))) + .any(|implem| implem.is_dependency(ty_name))) } else { false } diff --git a/src/core/mod.rs b/src/core/mod.rs index 2eee057a..99dc0d4e 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -57,14 +57,14 @@ impl<'a> Labeller<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> { } fn node_shape(&'a self, _node: &ItemState<'a>) -> Option> { - Some(LabelText::LabelStr(Cow::from(format!("record")))) + Some(LabelText::LabelStr(Cow::from("record"))) } fn node_label(&'a self, state: &ItemState<'a>) -> LabelText<'a> { - LabelText::LabelStr(format!("{}", state).into()) + LabelText::LabelStr(state.to_string().into()) } - fn edge_end_arrow(&'a self, ref seg: &Segment<'a>) -> Arrow { + fn edge_end_arrow(&'a self, seg: &Segment<'a>) -> Arrow { match ( seg.left.as_arrow(&seg.right), seg.right.as_arrow(&seg.left) @@ -74,7 +74,7 @@ impl<'a> Labeller<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> { } } - fn edge_style(&'a self, ref seg: &Segment<'a>) -> Style { + fn edge_style(&'a self, seg: &Segment<'a>) -> Style { if seg.left.is_realization(&seg.right).bitor(seg.left.is_dependency(&seg.right)) { Style::Dashed } else { diff --git a/src/module/mod.rs b/src/module/mod.rs index bd386c66..ac955ea6 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -35,7 +35,7 @@ impl IntoIterator for Module { type IntoIter = vec::IntoIter<(Item, Rc)>; fn into_iter(self) -> Self::IntoIter { - let ref rc: Rc = Rc::new(self.path); + let rc = &Rc::new(self.path); self.list.into_iter() .map(|item| (item, Rc::clone(rc))) .collect::)>>() From 70fdc4af021c68634de62c46edda9ec5a3299033 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Sat, 30 Jan 2021 15:56:30 +0100 Subject: [PATCH 09/11] Fix clippy lints --- src/core/item/mod.rs | 15 +++++++-------- src/core/item/state/mod.rs | 14 +++++++------- src/lib.rs | 22 +++++++++++----------- 3 files changed, 25 insertions(+), 26 deletions(-) diff --git a/src/core/item/mod.rs b/src/core/item/mod.rs index 47466546..762afac0 100644 --- a/src/core/item/mod.rs +++ b/src/core/item/mod.rs @@ -32,16 +32,15 @@ impl<'a> Iterator for Item<'a> { /// The method `next` will returns the first abstract elements defined like a structure, /// enumeration or trait. fn next(&mut self) -> Option> { - self.it.next().and_then(|item| { + self.it.next().map(|item| { let mut list: Vec<&'a (syn::Item, Rc)> = vec!(item); - list.extend(self.it.peeking_take_while(|(item, _)| - if let syn::Item::Impl(_) = item { - true - } else { - false - })); - Some(ItemState::from(list)) + list.extend(self.it + .peeking_take_while(|(item, _)| + matches!(item, syn::Item::Impl(_)) + ) + ); + ItemState::from(list) }) } } diff --git a/src/core/item/state/mod.rs b/src/core/item/state/mod.rs index b5e6a0bf..9abc2a38 100644 --- a/src/core/item/state/mod.rs +++ b/src/core/item/state/mod.rs @@ -17,9 +17,9 @@ pub mod implem; pub mod method; #[cfg(not(feature = "fn-emilgardis"))] -const DEFAULT_FUNC: &'static str = " "; +const DEFAULT_FUNC: &str = " "; #[cfg(feature = "fn-emilgardis")] -const DEFAULT_FUNC: &'static str = " fn "; +const DEFAULT_FUNC: &str = " fn "; /// The structure `ItemState` describes an abstract element with a collections of methodes /// and implementations. @@ -145,10 +145,10 @@ impl<'a> From<(Abstract<'a>, Vec<&'a (Item, Rc)>)> for ItemState<'a> impl<'a> From)>> for ItemState<'a> { fn from(state: Vec<&'a (Item, Rc)>) -> ItemState<'a> { - state.split_first().and_then(|(&&(ref item, ref path), properties): (&&'a (Item, Rc), &[&'a (Item, Rc)])| { - match &item { + state.split_first().and_then(|((item, path), properties)| { + match item { // Trait. - &Item::Trait(item) => { + Item::Trait(item) => { let ItemTrait { generics, items, .. } = item; let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME let kind: (_, &'a Vec, &'a Vec) = (item, ty_params, items); @@ -156,14 +156,14 @@ impl<'a> From)>> for ItemState<'a> { Some(ItemState::from(kind)) } // Structure with variables. - &Item::Struct(item) => { + Item::Struct(item) => { let fields = Box::leak(Box::new(item.fields.iter().cloned().collect())); // FIXME let kind: (_, &Vec) = (item, fields); let kind = (Abstract::Struct((kind, Rc::clone(path)).into()), properties.to_vec()); Some(ItemState::from(kind)) } // Enumeration with variables. - &Item::Enum(item) => { + Item::Enum(item) => { let ItemEnum { generics, variants, .. } = item; let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME let variants = Box::leak(Box::new(variants.iter().cloned().collect())); // FIXME diff --git a/src/lib.rs b/src/lib.rs index a2165352..be6f8853 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -45,9 +45,9 @@ pub mod module; pub mod core; /// The default name of *graph/dot* file. -pub const DEFAULT_NAME_DOT: &'static str = "ml.dot"; +pub const DEFAULT_NAME_DOT: &str = "ml.dot"; /// The default name of *image/svg* file. -pub const DEFAULT_NAME_PNG: &'static str = "ml.svg"; +pub const DEFAULT_NAME_PNG: &str = "ml.svg"; #[derive(Debug)] pub enum Error { @@ -93,15 +93,15 @@ fn file2crate>(path: P) -> Result { } /// The function `items2chars` returns a graph formated for *Graphiz/Dot*. -fn items2chars<'a>(modules: Vec) -> Result, Error> { +fn items2chars(modules: Vec) -> Result, Error> { let mut f: Vec = Vec::new(); let iter: Vec<(syn::Item, Rc)> = modules.into_iter() .flat_map(|s: Module| s.into_iter()) .collect::)>>(); - let iter: ListItem = ListItem::from(iter.as_slice().into_iter().peekable()); + let iter: ListItem = ListItem::from(iter.iter().peekable()); - dot::render(&iter, &mut f).and_then(|()| Ok(f)).map_err(Into::into) + dot::render(&iter, &mut f).map(|()| f).map_err(Into::into) } /// The function `rs2dot` returns graphed file module. @@ -114,8 +114,8 @@ fn items2chars<'a>(modules: Vec) -> Result, Error> { /// let _ = mml::rs2dot("src/lib.rs"); /// } /// ``` -pub fn rs2dot<'a, P: AsRef>(path: P) -> Result, Error> { - file2crate(path.as_ref()).and_then(|parse: syn::File| items2chars(vec![Module::from((parse.items, path.as_ref().to_path_buf()))]).into()) +pub fn rs2dot>(path: P) -> Result, Error> { + file2crate(path.as_ref()).and_then(|parse: syn::File| items2chars(vec![Module::from((parse.items, path.as_ref().to_path_buf()))])) } /// The function `src2dot` returns graphed repository of modules. @@ -128,7 +128,7 @@ pub fn rs2dot<'a, P: AsRef>(path: P) -> Result, Error> { /// let _ = mml::src2dot("src"); /// } /// ``` -pub fn src2dot<'a, P: AsRef>(path: P) -> Result, Error> { +pub fn src2dot>(path: P) -> Result, Error> { items2chars(WalkDir::new(path).into_iter() .filter_map(|entry: Result| entry.ok()) .filter(|entry| entry.file_type().is_file()) @@ -136,7 +136,7 @@ pub fn src2dot<'a, P: AsRef>(path: P) -> Result, Error> { let path: &Path = entry.path(); if path.extension().eq(&Some(OsStr::new("rs"))) { - file2crate(path).ok().and_then(|file| Some(Module::from((file.items, path.to_path_buf())))) + file2crate(path).ok().map(|file| Module::from((file.items, path.to_path_buf()))) } else { None } @@ -149,12 +149,12 @@ pub fn content2svg(buf: Vec) -> Result, Error> { Command::new("dot").arg("-Tsvg") .stdin(Stdio::piped()).stdout(Stdio::piped()) .spawn() - .and_then(|child| { + .map(|child| { let mut ret = vec![]; child.stdin.unwrap().write_all(buf.as_slice()).unwrap(); child.stdout.unwrap().read_to_end(&mut ret).unwrap(); - Ok(ret) + ret }).map_err(Into::into) } From fc24f0b012229b37742d5f429ce902d7d335ce43 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Sat, 30 Jan 2021 15:59:14 +0100 Subject: [PATCH 10/11] Run cargo fmt --- src/core/item/mod.rs | 19 +- src/core/item/relation.rs | 5 +- src/core/item/state/abstraction/enumerate.rs | 83 +++++--- src/core/item/state/abstraction/extend.rs | 130 ++++++++---- src/core/item/state/abstraction/mod.rs | 28 ++- src/core/item/state/abstraction/structure.rs | 56 +++-- src/core/item/state/implem.rs | 192 +++++++++++------- src/core/item/state/method.rs | 203 ++++++++++++------- src/core/item/state/mod.rs | 191 ++++++++++------- src/core/mod.rs | 58 +++--- src/core/segment.rs | 24 +-- src/lib.rs | 93 +++++---- src/module/mod.rs | 22 +- src/prelude.rs | 24 +-- tests/aggregation.rs | 10 +- tests/association.rs | 12 +- tests/composition.rs | 10 +- tests/dependency.rs | 12 +- tests/realization.rs | 34 +++- 19 files changed, 762 insertions(+), 444 deletions(-) diff --git a/src/core/item/mod.rs b/src/core/item/mod.rs index 762afac0..7055894c 100644 --- a/src/core/item/mod.rs +++ b/src/core/item/mod.rs @@ -1,9 +1,9 @@ -use std::{iter, slice}; use std::rc::Rc; +use std::{iter, slice}; -use ::itertools::Itertools; +use itertools::Itertools; -use ::module::path::ModulePath; +use module::path::ModulePath; pub use self::state::ItemState; @@ -20,9 +20,7 @@ pub struct Item<'a> { impl<'a> From)>>> for Item<'a> { /// The constructor method `from` returns a typed and iterable collection of abstract element. fn from(iter: iter::Peekable)>>) -> Item { - Item { - it: iter, - } + Item { it: iter } } } @@ -33,12 +31,11 @@ impl<'a> Iterator for Item<'a> { /// enumeration or trait. fn next(&mut self) -> Option> { self.it.next().map(|item| { - let mut list: Vec<&'a (syn::Item, Rc)> = vec!(item); + let mut list: Vec<&'a (syn::Item, Rc)> = vec![item]; - list.extend(self.it - .peeking_take_while(|(item, _)| - matches!(item, syn::Item::Impl(_)) - ) + list.extend( + self.it + .peeking_take_while(|(item, _)| matches!(item, syn::Item::Impl(_))), ); ItemState::from(list) }) diff --git a/src/core/item/relation.rs b/src/core/item/relation.rs index 6f9a2b54..2feb017d 100644 --- a/src/core/item/relation.rs +++ b/src/core/item/relation.rs @@ -1,4 +1,4 @@ -use ::dot::{ArrowShape, Fill, Side}; +use dot::{ArrowShape, Fill, Side}; use super::ItemState; @@ -14,7 +14,6 @@ pub enum Relation { } impl Relation { - /// The method `as_style` returns a stylized arrow (See *Table B.2 UML Edges* from [UML 2.5](http://www.omg.org/spec/UML/2.5). pub fn as_style(&self) -> ArrowShape { match self { @@ -28,7 +27,7 @@ impl Relation { } } -impl <'a>From<(&'a ItemState<'a>, &'a ItemState<'a>)> for Relation { +impl<'a> From<(&'a ItemState<'a>, &'a ItemState<'a>)> for Relation { fn from((left, right): (&'a ItemState<'a>, &'a ItemState<'a>)) -> Relation { if left.is_composition(right) { Relation::Composition diff --git a/src/core/item/state/abstraction/enumerate.rs b/src/core/item/state/abstraction/enumerate.rs index d4612f0d..0f3221de 100644 --- a/src/core/item/state/abstraction/enumerate.rs +++ b/src/core/item/state/abstraction/enumerate.rs @@ -1,11 +1,11 @@ use std::fmt; use std::rc::Rc; -use ::dot::escape_html; +use dot::escape_html; use quote::ToTokens; use syn::{Field, TypeParam, Variant}; -use ::module::path::ModulePath; +use module::path::ModulePath; /// The structure `Enum` is a enumerate abstract element. #[derive(Debug, Eq, PartialEq, Clone)] @@ -18,25 +18,41 @@ pub struct Enum<'a> { pub variants: Vec<(String, Vec)>, } -impl<'a> From<((&'a syn::ItemEnum, &'a Vec, &'a Vec), Rc)> for Enum<'a> { - fn from(((item, ty_params, variants), path): ((&'a syn::ItemEnum, &'a Vec, &'a Vec), Rc)) -> Enum<'a> { +impl<'a> + From<( + (&'a syn::ItemEnum, &'a Vec, &'a Vec), + Rc, + )> for Enum<'a> +{ + fn from( + ((item, ty_params, variants), path): ( + (&'a syn::ItemEnum, &'a Vec, &'a Vec), + Rc, + ), + ) -> Enum<'a> { Enum { path, vis: &item.vis, name: item.ident.to_string(), - params: ty_params.iter() + params: ty_params + .iter() .map(|param| param.ident.to_string()) .collect(), - variants: variants.iter() - .map(|Variant { ident, fields, .. }| - (ident.to_string(), if fields.is_empty() { - vec![] - } else { - fields.iter() - .map(|Field { ty, .. }| - ty.to_token_stream().to_string() - ).collect() - })) + variants: variants + .iter() + .map(|Variant { ident, fields, .. }| { + ( + ident.to_string(), + if fields.is_empty() { + vec![] + } else { + fields + .iter() + .map(|Field { ty, .. }| ty.to_token_stream().to_string()) + .collect() + }, + ) + }) .collect(), } } @@ -45,24 +61,29 @@ impl<'a> From<((&'a syn::ItemEnum, &'a Vec, &'a Vec), Rc fmt::Display for Enum<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if self.variants.is_empty() { - write!(f, "<<<Enumeration>>>\n{name}", name = self.name) + write!( + f, + "<<<Enumeration>>>\n{name}", + name = self.name + ) } else { - write!(f, "<<<Enumeration>>>\n{name}|{variants}", - name = self.name, - variants = escape_html(self.variants.iter() - .map(|( name, struct_field)| - if struct_field.is_empty() { - name.to_owned() - } else { - format!("{}({})", name, struct_field.join(", ")) - } - ) - .collect::>() - .join("\n") - .as_str()), + write!( + f, + "<<<Enumeration>>>\n{name}|{variants}", + name = self.name, + variants = escape_html( + self.variants + .iter() + .map(|(name, struct_field)| if struct_field.is_empty() { + name.to_owned() + } else { + format!("{}({})", name, struct_field.join(", ")) + }) + .collect::>() + .join("\n") + .as_str() + ), ) } } } - - diff --git a/src/core/item/state/abstraction/extend.rs b/src/core/item/state/abstraction/extend.rs index a34c6bb3..2d01bc1d 100644 --- a/src/core/item/state/abstraction/extend.rs +++ b/src/core/item/state/abstraction/extend.rs @@ -1,11 +1,14 @@ use std::fmt; use std::rc::Rc; -use ::dot::escape_html; +use dot::escape_html; use quote::ToTokens; -use syn::{FnArg, ItemTrait, PatType, Receiver, ReturnType, Signature, TraitItem, TraitItemMethod, TypeParam, Visibility}; +use syn::{ + FnArg, ItemTrait, PatType, Receiver, ReturnType, Signature, TraitItem, TraitItemMethod, + TypeParam, Visibility, +}; -use ::module::path::ModulePath; +use module::path::ModulePath; #[derive(Debug, Eq, PartialEq, Clone)] pub struct Trait<'a> { @@ -17,39 +20,81 @@ pub struct Trait<'a> { pub items: Vec<(String, Vec, String)>, } -impl<'a> From<((&'a ItemTrait, &'a Vec, &'a Vec), Rc)> for Trait<'a> { - fn from(((item, ty_params, trait_item), path): ((&'a ItemTrait, &'a Vec, &'a Vec), Rc)) -> Trait<'a> { +impl<'a> + From<( + (&'a ItemTrait, &'a Vec, &'a Vec), + Rc, + )> for Trait<'a> +{ + fn from( + ((item, ty_params, trait_item), path): ( + (&'a ItemTrait, &'a Vec, &'a Vec), + Rc, + ), + ) -> Trait<'a> { Trait { path, vis: &item.vis, name: item.ident.to_string(), - params: ty_params.iter() + params: ty_params + .iter() .map(|TypeParam { ident, .. }| ident.to_string()) .collect(), - items: trait_item.iter() - .filter_map(|item: &TraitItem| - if let TraitItem::Method(TraitItemMethod { sig: Signature { ident, inputs, output: ReturnType::Type(_, output), .. }, .. }) = item { - Some((ident.to_string(), inputs.iter().map(|input| { - dbg!(input); - match input { - FnArg::Typed(PatType { ty, .. }) => { - ty.to_token_stream().to_string() - } - FnArg::Receiver(Receiver { reference, mutability, .. }) => { // FIXME - let (r1, r2) = match reference { - Some((and, lifetime)) => (Some(and.to_token_stream().to_string()), Some(lifetime.to_token_stream().to_string())), - None => (None, None) - }; - let mutability = Some(mutability.to_token_stream().to_string()); - let s = Some(" Self".into()); - [r1, r2, mutability, s].iter().flatten().map(ToString::to_string).collect() - } - } - }).collect(), output.to_token_stream().to_string())) + items: trait_item + .iter() + .filter_map(|item: &TraitItem| { + if let TraitItem::Method(TraitItemMethod { + sig: + Signature { + ident, + inputs, + output: ReturnType::Type(_, output), + .. + }, + .. + }) = item + { + Some(( + ident.to_string(), + inputs + .iter() + .map(|input| { + dbg!(input); + match input { + FnArg::Typed(PatType { ty, .. }) => { + ty.to_token_stream().to_string() + } + FnArg::Receiver(Receiver { + reference, + mutability, + .. + }) => { + // FIXME + let (r1, r2) = match reference { + Some((and, lifetime)) => ( + Some(and.to_token_stream().to_string()), + Some(lifetime.to_token_stream().to_string()), + ), + None => (None, None), + }; + let mutability = + Some(mutability.to_token_stream().to_string()); + let s = Some(" Self".into()); + [r1, r2, mutability, s] + .iter() + .flatten() + .map(ToString::to_string) + .collect() + } + } + }) + .collect(), + output.to_token_stream().to_string(), + )) } else { None } - ) + }) .collect::, String)>>(), } } @@ -57,18 +102,25 @@ impl<'a> From<((&'a ItemTrait, &'a Vec, &'a Vec), Rc fmt::Display for Trait<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "<<<Trait>>>\n{name}|{items}", - name = self.name, - items = escape_html(self.items.iter() - .map(|&(ref name, ref ty, ref ret): &(String, Vec, String)| - format!("{name}({ty}) -> {ret}", - name = name, - ty = ty.join(", "), - ret = ret - )) - .collect::>() - .join("\n") - .as_str()) + write!( + f, + "<<<Trait>>>\n{name}|{items}", + name = self.name, + items = escape_html( + self.items + .iter() + .map( + |&(ref name, ref ty, ref ret): &(String, Vec, String)| format!( + "{name}({ty}) -> {ret}", + name = name, + ty = ty.join(", "), + ret = ret + ) + ) + .collect::>() + .join("\n") + .as_str() + ) ) } } diff --git a/src/core/item/state/abstraction/mod.rs b/src/core/item/state/abstraction/mod.rs index ee573d2a..b105bd01 100644 --- a/src/core/item/state/abstraction/mod.rs +++ b/src/core/item/state/abstraction/mod.rs @@ -7,9 +7,9 @@ use self::enumerate::Enum; use self::extend::Trait; use self::structure::Struct; +pub mod enumerate; pub mod extend; pub mod structure; -pub mod enumerate; /// The structure `Abstract` is a enumerate for abstract element types or none. #[derive(Debug, Eq, PartialEq, Clone)] @@ -39,21 +39,17 @@ impl<'a> IntoIterator for &'a Abstract<'a> { fn into_iter(self) -> Self::IntoIter { match self { - Abstract::Struct(Struct { fields, .. }) => { - fields.iter() - .map(|&(_, _, ref ty): &'a (&'a Visibility, String, String)| ty) - .collect::>() - .into_iter() - } - Abstract::Enum(Enum { variants, .. }) => { - variants.iter() - .map(|(_, ty_field)| - ty_field.iter() - .collect::>()) - .collect::>>() - .concat() - .into_iter() - } + Abstract::Struct(Struct { fields, .. }) => fields + .iter() + .map(|&(_, _, ref ty): &'a (&'a Visibility, String, String)| ty) + .collect::>() + .into_iter(), + Abstract::Enum(Enum { variants, .. }) => variants + .iter() + .map(|(_, ty_field)| ty_field.iter().collect::>()) + .collect::>>() + .concat() + .into_iter(), _ => Vec::default().into_iter(), } } diff --git a/src/core/item/state/abstraction/structure.rs b/src/core/item/state/abstraction/structure.rs index 69eb8f6f..8ef55afb 100644 --- a/src/core/item/state/abstraction/structure.rs +++ b/src/core/item/state/abstraction/structure.rs @@ -2,11 +2,11 @@ use std::fmt; use std::fmt::{Debug, Formatter}; use std::rc::Rc; -use ::dot::escape_html; +use dot::escape_html; use quote::ToTokens; use syn::{Field, ItemStruct, Visibility}; -use ::module::path::ModulePath; +use module::path::ModulePath; /// The structure `Struct` is a structure abstract element. #[derive(Debug, Eq, PartialEq, Clone)] @@ -19,15 +19,22 @@ pub struct Struct<'a> { } impl<'a> From<((&'a ItemStruct, &'a Vec), Rc)> for Struct<'a> { - fn from(((item, struct_field), path): ((&'a ItemStruct, &'a Vec), Rc)) -> Struct<'a> { + fn from( + ((item, struct_field), path): ((&'a ItemStruct, &'a Vec), Rc), + ) -> Struct<'a> { Struct { path, vis: &item.vis, name: item.ident.to_string(), - fields: struct_field.iter() + fields: struct_field + .iter() .enumerate() .map(|(index, Field { vis, ident, ty, .. })| { - let ident = if let Some(ident) = ident { ident.to_string() } else { index.to_string() }; + let ident = if let Some(ident) = ident { + ident.to_string() + } else { + index.to_string() + }; (vis, ident, ty.to_token_stream().to_string()) }) .collect(), @@ -38,21 +45,32 @@ impl<'a> From<((&'a ItemStruct, &'a Vec), Rc)> for Struct<'a> impl<'a> fmt::Display for Struct<'a> { fn fmt(&self, f: &mut Formatter) -> fmt::Result { if self.fields.is_empty() { - write!(f, "<<<Structure>>>\n{name}", name = self.name) + write!( + f, + "<<<Structure>>>\n{name}", + name = self.name + ) } else { - write!(f, "<<<Structure>>>\n{name}|{fields}", - name = self.name, - fields = escape_html(self.fields.iter() - .map(|&(ref vis, ref name, ref ty): &(&Visibility, String, String)| - if let Visibility::Public(_) = vis { - format!("+ {name}: {ty}", name = name, ty = ty) - } else { - format!("- {name}: {ty}", name = name, ty = ty) - } - ) - .collect::>() - .join("\n") - .as_str()), + write!( + f, + "<<<Structure>>>\n{name}|{fields}", + name = self.name, + fields = escape_html( + self.fields + .iter() + .map( + |&(ref vis, ref name, ref ty): &(&Visibility, String, String)| { + if let Visibility::Public(_) = vis { + format!("+ {name}: {ty}", name = name, ty = ty) + } else { + format!("- {name}: {ty}", name = name, ty = ty) + } + } + ) + .collect::>() + .join("\n") + .as_str() + ), ) } } diff --git a/src/core/item/state/implem.rs b/src/core/item/state/implem.rs index f01976da..f8c5f9f7 100644 --- a/src/core/item/state/implem.rs +++ b/src/core/item/state/implem.rs @@ -1,10 +1,13 @@ use std::fmt; -use ::dot::escape_html; +use dot::escape_html; use quote::ToTokens; -use syn::{AngleBracketedGenericArguments, FnArg, GenericArgument, ImplItem, ImplItemMethod, PathArguments, PathSegment, ReturnType, Signature}; use syn::punctuated::Punctuated; use syn::token::Colon2; +use syn::{ + AngleBracketedGenericArguments, FnArg, GenericArgument, ImplItem, ImplItemMethod, + PathArguments, PathSegment, ReturnType, Signature, +}; use super::DEFAULT_FUNC; @@ -26,89 +29,142 @@ impl Implem { } pub fn is_association(&self, ty_name: &str) -> bool { - self.method.iter() - .any(|(_, _, result)| - if let Some(ret) = result { - ret.split(|at| "<[(;, )]>".contains(at)) - .any(|ty| ty.eq(ty_name)) - } else { - false - } - ) + self.method.iter().any(|(_, _, result)| { + if let Some(ret) = result { + ret.split(|at| "<[(;, )]>".contains(at)) + .any(|ty| ty.eq(ty_name)) + } else { + false + } + }) } pub fn is_dependency(&self, _: &str) -> bool { false /*self.method.iter() - .any(|&( _, ref arg, _): &(String, Vec, Option)| - arg.iter().any(|ty| ty.ends_with(name)))*/ + .any(|&( _, ref arg, _): &(String, Vec, Option)| + arg.iter().any(|ty| ty.ends_with(name)))*/ } } -impl From<(Vec<(String, Vec)>, Vec<(String, Vec, Option)>)> for Implem { - fn from((ty, method): (Vec<(String, Vec)>, Vec<(String, Vec, Option)>)) -> Implem { - Implem { - ty, - method, - } +impl + From<( + Vec<(String, Vec)>, + Vec<(String, Vec, Option)>, + )> for Implem +{ + fn from( + (ty, method): ( + Vec<(String, Vec)>, + Vec<(String, Vec, Option)>, + ), + ) -> Implem { + Implem { ty, method } } } impl<'a> From<(&'a Punctuated, &'a Vec)> for Implem { - fn from((segments, impl_item): (&'a Punctuated, &'a Vec)) -> Implem { - Implem::from((segments.iter() - .map(|PathSegment { ident, arguments, .. }| { - if let PathArguments::AngleBracketed(AngleBracketedGenericArguments { args, .. }) = arguments { - (ident.to_string(), args.iter() - .filter_map(|ty| - if let GenericArgument::Type(ty) = ty { - Some(ty.to_token_stream().to_string()) - } else { - None - }) - .collect::>()) - } else { - (ident.to_string(), Vec::new()) - } - }) - .collect::)>>(), - impl_item.iter() - .filter_map(|item| { - if let ImplItem::Method(ImplItemMethod { sig: Signature { ident, inputs, output, .. }, .. }) = item { - let inputs = inputs.iter() - .filter_map(|arg| - if let FnArg::Typed(ty) = arg { - Some(ty.ty.to_token_stream().to_string()) - } else { - None - }) - .collect(); - if let ReturnType::Type(_, ref ty) = output { - Some((ident.to_string(), inputs, Some(ty.to_token_stream().to_string()))) - } else { - Some((ident.to_string(), inputs, None)) - } - } else { - None - } - }).collect::, Option)>>())) + fn from( + (segments, impl_item): (&'a Punctuated, &'a Vec), + ) -> Implem { + Implem::from(( + segments + .iter() + .map( + |PathSegment { + ident, arguments, .. + }| { + if let PathArguments::AngleBracketed(AngleBracketedGenericArguments { + args, + .. + }) = arguments + { + ( + ident.to_string(), + args.iter() + .filter_map(|ty| { + if let GenericArgument::Type(ty) = ty { + Some(ty.to_token_stream().to_string()) + } else { + None + } + }) + .collect::>(), + ) + } else { + (ident.to_string(), Vec::new()) + } + }, + ) + .collect::)>>(), + impl_item + .iter() + .filter_map(|item| { + if let ImplItem::Method(ImplItemMethod { + sig: + Signature { + ident, + inputs, + output, + .. + }, + .. + }) = item + { + let inputs = inputs + .iter() + .filter_map(|arg| { + if let FnArg::Typed(ty) = arg { + Some(ty.ty.to_token_stream().to_string()) + } else { + None + } + }) + .collect(); + if let ReturnType::Type(_, ref ty) = output { + Some(( + ident.to_string(), + inputs, + Some(ty.to_token_stream().to_string()), + )) + } else { + Some((ident.to_string(), inputs, None)) + } + } else { + None + } + }) + .collect::, Option)>>(), + )) } } impl fmt::Display for Implem { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{item}", - item = escape_html(self.method.iter() - .map(|&(ref name, ref args, ref result): &(String, Vec, Option)| { - if let Some(ret) = result { - format!("{}{}({}) -> {}", DEFAULT_FUNC, name, args.join(", "), ret) - } else { - format!("{}{}({})", DEFAULT_FUNC, name, args.join(", ")) - } - }) - .collect::>() - .join("\n") - .as_str())) + write!( + f, + "{item}", + item = escape_html( + self.method + .iter() + .map( + |&(ref name, ref args, ref result): &( + String, + Vec, + Option + )| { + if let Some(ret) = result { + format!("{}{}({}) -> {}", DEFAULT_FUNC, name, args.join(", "), ret) + } else { + format!("{}{}({})", DEFAULT_FUNC, name, args.join(", ")) + } + } + ) + .collect::>() + .join("\n") + .as_str() + ) + ) /*if let Some(&(ref name, ref template)) = self.ty.last() { if template.is_empty() { write!(f, "{name}", name = name.to_string()) diff --git a/src/core/item/state/method.rs b/src/core/item/state/method.rs index 3984d7a9..388efe0a 100644 --- a/src/core/item/state/method.rs +++ b/src/core/item/state/method.rs @@ -1,21 +1,14 @@ use std::fmt; use std::rc::Rc; -use ::dot::escape_html; +use dot::escape_html; use quote::ToTokens; use syn::{ - FnArg, - ImplItem, - ImplItemMethod, - punctuated::Punctuated, - ReturnType, - Signature, - token::Comma, - Type, - Visibility, + punctuated::Punctuated, token::Comma, FnArg, ImplItem, ImplItemMethod, ReturnType, Signature, + Type, Visibility, }; -use ::module::path::ModulePath; +use module::path::ModulePath; use super::DEFAULT_FUNC; @@ -23,93 +16,161 @@ use super::DEFAULT_FUNC; #[derive(Default, Debug, Clone, Eq, PartialEq)] pub struct Method<'a> { /// visibility, method's name, arguments, result. - func: Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, + func: Vec<( + &'a Visibility, + String, + &'a Punctuated, + Option<&'a Box>, + )>, path: Rc, } impl<'a> Method<'a> { pub fn is_association(&self, ty_name: &str) -> bool { - self.func.iter() - .any(|(_, _, _, result)| - if let Some(ret) = result { - // TODO: replace by checking if ret (which is of type Type) - // TODO: contains ty_name anywhere - ret.to_token_stream().to_string().split(|at| "<[(;, )]>".contains(at)) - .any(|ty| ty.eq(ty_name)) - } else { - false - } - ) + self.func.iter().any(|(_, _, _, result)| { + if let Some(ret) = result { + // TODO: replace by checking if ret (which is of type Type) + // TODO: contains ty_name anywhere + ret.to_token_stream() + .to_string() + .split(|at| "<[(;, )]>".contains(at)) + .any(|ty| ty.eq(ty_name)) + } else { + false + } + }) } pub fn is_dependency(&self, name: &str) -> bool { - self.func.iter() - .any(|(_, _, arg, _)| - arg.iter().filter_map(|ty| { + self.func.iter().any(|(_, _, arg, _)| { + arg.iter() + .filter_map(|ty| { if let FnArg::Typed(ty) = ty { Some(ty) } else { None } }) - .any(|ty| ty.ty.to_token_stream().to_string().ends_with(name))) + .any(|ty| ty.ty.to_token_stream().to_string().ends_with(name)) + }) } } -impl<'a> From<(Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, Rc)> for Method<'a> { - fn from((func, path): (Vec<(&'a Visibility, String, &'a Punctuated, Option<&'a Box>)>, Rc)) -> Method<'a> { - Method { - func, - path, - } +impl<'a> + From<( + Vec<( + &'a Visibility, + String, + &'a Punctuated, + Option<&'a Box>, + )>, + Rc, + )> for Method<'a> +{ + fn from( + (func, path): ( + Vec<( + &'a Visibility, + String, + &'a Punctuated, + Option<&'a Box>, + )>, + Rc, + ), + ) -> Method<'a> { + Method { func, path } } } impl<'a> From<(&'a Vec, Rc)> for Method<'a> { fn from((impl_item, path): (&'a Vec, Rc)) -> Method<'a> { - Method::from((impl_item.iter() - .filter_map(|item| { - if let ImplItem::Method(ImplItemMethod { ref vis, ref sig, .. }) = item { - if let Signature { ident, inputs, output: ReturnType::Default, .. } = sig { - Some((vis, ident.to_string(), inputs, None)) - } else if let Signature { ident, inputs, output: ReturnType::Type(_, ref output), .. } = sig { - Some((vis, ident.to_string(), inputs, Some(output))) - } else { - None - } - } else { - None - } - }) - .collect::>(), - path)) + Method::from(( + impl_item + .iter() + .filter_map(|item| { + if let ImplItem::Method(ImplItemMethod { + ref vis, ref sig, .. + }) = item + { + if let Signature { + ident, + inputs, + output: ReturnType::Default, + .. + } = sig + { + Some((vis, ident.to_string(), inputs, None)) + } else if let Signature { + ident, + inputs, + output: ReturnType::Type(_, ref output), + .. + } = sig + { + Some((vis, ident.to_string(), inputs, Some(output))) + } else { + None + } + } else { + None + } + }) + .collect::>(), + path, + )) } } impl<'a> fmt::Display for Method<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{item}", - item = escape_html(self.func.iter() - .map(|&(vis, ref name, ref inputs, ty)| { - match (vis, ty) { - (Visibility::Public(_), Some(ty)) => { - format!("+{}{}({}) -> {}", DEFAULT_FUNC, name, inputs.to_token_stream().to_string(), ty.to_token_stream().to_string()) - } - (Visibility::Public(_), None) => { - format!("+{}{}({})", DEFAULT_FUNC, name, inputs.to_token_stream().to_string()) - } - (_, Some(ty)) => { - format!("-{}{}({}) -> {}", DEFAULT_FUNC, name, inputs.to_token_stream().to_string(), ty.to_token_stream().to_string()) - } - (_, None) => { - format!("-{}{}({})", DEFAULT_FUNC, name, inputs.to_token_stream().to_string()) - } - } - } - ) - .collect::>() - .join("\n") - .as_str()) + write!( + f, + "{item}", + item = escape_html( + self.func + .iter() + .map(|&(vis, ref name, ref inputs, ty)| { + match (vis, ty) { + (Visibility::Public(_), Some(ty)) => { + format!( + "+{}{}({}) -> {}", + DEFAULT_FUNC, + name, + inputs.to_token_stream().to_string(), + ty.to_token_stream().to_string() + ) + } + (Visibility::Public(_), None) => { + format!( + "+{}{}({})", + DEFAULT_FUNC, + name, + inputs.to_token_stream().to_string() + ) + } + (_, Some(ty)) => { + format!( + "-{}{}({}) -> {}", + DEFAULT_FUNC, + name, + inputs.to_token_stream().to_string(), + ty.to_token_stream().to_string() + ) + } + (_, None) => { + format!( + "-{}{}({})", + DEFAULT_FUNC, + name, + inputs.to_token_stream().to_string() + ) + } + } + }) + .collect::>() + .join("\n") + .as_str() + ) ) } } diff --git a/src/core/item/state/mod.rs b/src/core/item/state/mod.rs index 9abc2a38..6d449c38 100644 --- a/src/core/item/state/mod.rs +++ b/src/core/item/state/mod.rs @@ -4,7 +4,7 @@ use std::rc::Rc; use syn::{Field, Item, ItemEnum, ItemImpl, ItemTrait, Path, TraitItem, TypeParam, Variant}; -use ::module::path::ModulePath; +use module::path::ModulePath; use super::relation::Relation; @@ -40,10 +40,14 @@ impl<'a> ItemState<'a> { pub fn is_association(&self, rhs: &ItemState<'a>) -> bool { if let Some(ty_name) = self.as_name() { - rhs.method.iter() + rhs.method + .iter() .any(|func| func.is_association(ty_name)) - .bitor(rhs.implem.iter() - .any(|implem| implem.is_association(ty_name))) + .bitor( + rhs.implem + .iter() + .any(|implem| implem.is_association(ty_name)), + ) } else { false } @@ -51,10 +55,14 @@ impl<'a> ItemState<'a> { pub fn is_dependency(&self, rhs: &ItemState<'a>) -> bool { if let Some(ty_name) = self.as_name() { - rhs.method.iter() + rhs.method + .iter() .any(|method| method.is_dependency(ty_name)) - .bitor(self.implem.iter() - .any(|implem| implem.is_dependency(ty_name))) + .bitor( + self.implem + .iter() + .any(|implem| implem.is_dependency(ty_name)), + ) } else { false } @@ -67,10 +75,11 @@ impl<'a> ItemState<'a> { ty_name_mut.push_str(&name); ty_name_const.push_str(&name); - rhs.node.into_iter() - .any(|attribut: &String| - attribut.split(|at| "<[(;,)]>".contains(at)) - .any(|ty| ty_name_mut.eq(ty).bitor(ty_name_const.eq(ty)))) + rhs.node.into_iter().any(|attribut: &String| { + attribut + .split(|at| "<[(;,)]>".contains(at)) + .any(|ty| ty_name_mut.eq(ty).bitor(ty_name_const.eq(ty))) + }) } else { false } @@ -80,10 +89,11 @@ impl<'a> ItemState<'a> { if let Some(ref name) = self.as_name() { let ty_name: String = name.to_string(); - rhs.node.into_iter() - .any(|attribut: &String| - attribut.split(|at| "<[(;,)]>".contains(at)) - .any(|ty| ty.eq(&ty_name))) + rhs.node.into_iter().any(|attribut: &String| { + attribut + .split(|at| "<[(;,)]>".contains(at)) + .any(|ty| ty.eq(&ty_name)) + }) } else { false } @@ -93,7 +103,8 @@ impl<'a> ItemState<'a> { if let Some(ref name) = self.as_name() { let ty_name: String = name.to_string(); - rhs.implem.iter() + rhs.implem + .iter() .any(|implem| implem.is_realization(&ty_name)) } else { false @@ -121,23 +132,29 @@ impl<'a> From<(Abstract<'a>, Vec<&'a (Item, Rc)>)> for ItemState<'a> fn from((node, properties): (Abstract<'a>, Vec<&'a (Item, Rc)>)) -> ItemState<'a> { ItemState { node, - method: properties.iter() - .filter_map(|(item, path)| - match item { - Item::Impl(ItemImpl { trait_, items, .. }) - if trait_.is_none() => Some(Method::from((items, Rc::clone(path)))), - _ => None, + method: properties + .iter() + .filter_map(|(item, path)| match item { + Item::Impl(ItemImpl { trait_, items, .. }) if trait_.is_none() => { + Some(Method::from((items, Rc::clone(path)))) } - ) + _ => None, + }) .collect(), - implem: properties.iter() - .filter_map(|(item, _)| - if let Item::Impl(ItemImpl { trait_: Some((_, Path { segments, .. }, _)), items, .. }) = item { + implem: properties + .iter() + .filter_map(|(item, _)| { + if let Item::Impl(ItemImpl { + trait_: Some((_, Path { segments, .. }, _)), + items, + .. + }) = item + { Some(Implem::from((segments, items))) } else { None } - ) + }) .collect(), } } @@ -145,49 +162,80 @@ impl<'a> From<(Abstract<'a>, Vec<&'a (Item, Rc)>)> for ItemState<'a> impl<'a> From)>> for ItemState<'a> { fn from(state: Vec<&'a (Item, Rc)>) -> ItemState<'a> { - state.split_first().and_then(|((item, path), properties)| { - match item { - // Trait. - Item::Trait(item) => { - let ItemTrait { generics, items, .. } = item; - let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME - let kind: (_, &'a Vec, &'a Vec) = (item, ty_params, items); - let kind: (Abstract, Vec<&'a (Item, Rc)>) = (Abstract::Trait((kind, Rc::clone(path)).into()), properties.to_vec()); - Some(ItemState::from(kind)) - } - // Structure with variables. - Item::Struct(item) => { - let fields = Box::leak(Box::new(item.fields.iter().cloned().collect())); // FIXME - let kind: (_, &Vec) = (item, fields); - let kind = (Abstract::Struct((kind, Rc::clone(path)).into()), properties.to_vec()); - Some(ItemState::from(kind)) - } - // Enumeration with variables. - Item::Enum(item) => { - let ItemEnum { generics, variants, .. } = item; - let ty_params = Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME - let variants = Box::leak(Box::new(variants.iter().cloned().collect())); // FIXME - let kind: (&'a ItemEnum, &'a Vec, &'a Vec) = (item, ty_params, variants); - let kind: (Abstract, Vec<&'a (Item, Rc)>) = (Abstract::Enum((kind, Rc::clone(path)).into()), properties.to_vec()); - Some(ItemState::from(kind)) + state + .split_first() + .and_then(|((item, path), properties)| { + match item { + // Trait. + Item::Trait(item) => { + let ItemTrait { + generics, items, .. + } = item; + let ty_params = + Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME + let kind: (_, &'a Vec, &'a Vec) = + (item, ty_params, items); + let kind: (Abstract, Vec<&'a (Item, Rc)>) = ( + Abstract::Trait((kind, Rc::clone(path)).into()), + properties.to_vec(), + ); + Some(ItemState::from(kind)) + } + // Structure with variables. + Item::Struct(item) => { + let fields = Box::leak(Box::new(item.fields.iter().cloned().collect())); // FIXME + let kind: (_, &Vec) = (item, fields); + let kind = ( + Abstract::Struct((kind, Rc::clone(path)).into()), + properties.to_vec(), + ); + Some(ItemState::from(kind)) + } + // Enumeration with variables. + Item::Enum(item) => { + let ItemEnum { + generics, variants, .. + } = item; + let ty_params = + Box::leak(Box::new(generics.type_params().cloned().collect())); // FIXME + let variants = Box::leak(Box::new(variants.iter().cloned().collect())); // FIXME + let kind: (&'a ItemEnum, &'a Vec, &'a Vec) = + (item, ty_params, variants); + let kind: (Abstract, Vec<&'a (Item, Rc)>) = ( + Abstract::Enum((kind, Rc::clone(path)).into()), + properties.to_vec(), + ); + Some(ItemState::from(kind)) + } + _ => None, } - _ => None, - } - }).unwrap_or_default() + }) + .unwrap_or_default() } } impl<'a> fmt::Display for ItemState<'a> { #[cfg(feature = "implem")] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{{{node}|{method}|{implem}}}", - node = self.node, - method = self.method.iter() - .map(|ref methods| format!("{}", methods)) - .collect::>().join("\n").as_str(), - implem = self.implem.iter() - .map(|ref implem| format!("{}", implem)) - .collect::>().join("\n").as_str()) + write!( + f, + "{{{node}|{method}|{implem}}}", + node = self.node, + method = self + .method + .iter() + .map(|ref methods| format!("{}", methods)) + .collect::>() + .join("\n") + .as_str(), + implem = self + .implem + .iter() + .map(|ref implem| format!("{}", implem)) + .collect::>() + .join("\n") + .as_str() + ) } #[cfg(not(feature = "implem"))] @@ -195,11 +243,18 @@ impl<'a> fmt::Display for ItemState<'a> { if self.method.is_empty() { write!(f, "{{{node}}}", node = self.node) } else { - write!(f, "{{{node}|{method}}}", - node = self.node, - method = self.method.iter() - .map(|ref methods| format!("{}", methods)) - .collect::>().join("\n").as_str()) + write!( + f, + "{{{node}|{method}}}", + node = self.node, + method = self + .method + .iter() + .map(|ref methods| format!("{}", methods)) + .collect::>() + .join("\n") + .as_str() + ) } } } diff --git a/src/core/mod.rs b/src/core/mod.rs index 99dc0d4e..860748e6 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,21 +1,21 @@ //! Core Syntax and definitions. -use std::{iter, slice}; use std::borrow::Cow; use std::ops::BitOr; use std::rc::Rc; +use std::{iter, slice}; -use ::dot::{Arrow, Edges, GraphWalk, Id, Labeller, LabelText, Nodes, Style}; -use ::itertools::Itertools; +use dot::{Arrow, Edges, GraphWalk, Id, LabelText, Labeller, Nodes, Style}; +use itertools::Itertools; -use ::module::path::ModulePath; +use module::path::ModulePath; -use self::item::{Item, ItemState}; use self::item::relation::Relation; +use self::item::{Item, ItemState}; use self::segment::Segment; -pub mod segment; pub mod item; +pub mod segment; #[derive(Debug, Clone)] pub struct ListItem<'a> { @@ -24,9 +24,7 @@ pub struct ListItem<'a> { impl<'a> From> for ListItem<'a> { fn from(parse: Item<'a>) -> ListItem<'a> { - ListItem { - parse, - } + ListItem { parse } } } @@ -40,7 +38,10 @@ impl<'a> Iterator for ListItem<'a> { type Item = ItemState<'a>; fn next(&mut self) -> Option> { - self.parse.by_ref().skip_while(|state| state.is_none()).next() + self.parse + .by_ref() + .skip_while(|state| state.is_none()) + .next() } } @@ -65,17 +66,18 @@ impl<'a> Labeller<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> { } fn edge_end_arrow(&'a self, seg: &Segment<'a>) -> Arrow { - match ( - seg.left.as_arrow(&seg.right), - seg.right.as_arrow(&seg.left) - ) { + match (seg.left.as_arrow(&seg.right), seg.right.as_arrow(&seg.left)) { (Relation::Association, Relation::Association) => Arrow::none(), (edge_left, _) => Arrow::from_arrow(edge_left.as_style()), } } fn edge_style(&'a self, seg: &Segment<'a>) -> Style { - if seg.left.is_realization(&seg.right).bitor(seg.left.is_dependency(&seg.right)) { + if seg + .left + .is_realization(&seg.right) + .bitor(seg.left.is_dependency(&seg.right)) + { Style::Dashed } else { Style::None @@ -93,13 +95,17 @@ impl<'a> GraphWalk<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> { let dbg = items.iter().map(|s| format!("{:?}", s)).collect::>(); println!("{:#?}", dbg); - - let items = items.iter() - .map(|item| items.iter() - .filter(|rhs| item.ne(rhs)) - .filter(|rhs| item.is_relation(rhs)) - .map(|rhs| Segment::from((item.clone(), rhs.clone()))) - .collect::>>()) + + let items = items + .iter() + .map(|item| { + items + .iter() + .filter(|rhs| item.ne(rhs)) + .filter(|rhs| item.is_relation(rhs)) + .map(|rhs| Segment::from((item.clone(), rhs.clone()))) + .collect::>>() + }) .collect::>>>() .concat() .into_iter() @@ -109,7 +115,11 @@ impl<'a> GraphWalk<'a, ItemState<'a>, Segment<'a>> for ListItem<'a> { Cow::Owned(items) } - fn source(&self, seg: &Segment<'a>) -> ItemState<'a> { seg.left.clone() } + fn source(&self, seg: &Segment<'a>) -> ItemState<'a> { + seg.left.clone() + } - fn target(&self, seg: &Segment<'a>) -> ItemState<'a> { seg.right.clone() } + fn target(&self, seg: &Segment<'a>) -> ItemState<'a> { + seg.right.clone() + } } diff --git a/src/core/segment.rs b/src/core/segment.rs index d1fcf1ec..91360026 100644 --- a/src/core/segment.rs +++ b/src/core/segment.rs @@ -1,5 +1,5 @@ -use std::ops::{BitOr, BitAnd}; use std::hash::{Hash, Hasher}; +use std::ops::{BitAnd, BitOr}; use super::ItemState; @@ -11,25 +11,21 @@ pub struct Segment<'a> { pub right: ItemState<'a>, } -impl <'a> From<(ItemState<'a>, ItemState<'a>)> for Segment <'a> { +impl<'a> From<(ItemState<'a>, ItemState<'a>)> for Segment<'a> { fn from((left, right): (ItemState<'a>, ItemState<'a>)) -> Segment<'a> { - Segment { - left, - right, - } + Segment { left, right } } } -impl <'a> Hash for Segment <'a> { - fn hash(&self, _: &mut H) { - } +impl<'a> Hash for Segment<'a> { + fn hash(&self, _: &mut H) {} } -impl <'a> PartialEq for Segment <'a> { +impl<'a> PartialEq for Segment<'a> { fn eq(&self, rhs: &Segment) -> bool { - self.left.eq(&rhs.left) - .bitand(self.right.eq(&rhs.right)) - .bitor(self.left.eq(&rhs.right) - .bitand(self.right.eq(&rhs.left))) + self.left + .eq(&rhs.left) + .bitand(self.right.eq(&rhs.right)) + .bitor(self.left.eq(&rhs.right).bitand(self.right.eq(&rhs.left))) } } diff --git a/src/lib.rs b/src/lib.rs index be6f8853..53441af8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,29 +1,26 @@ #![crate_name = "mml"] #![crate_type = "lib"] - #![doc(html_root_url = "https://docs.rs/mml/0.1.41")] - #![cfg_attr(feature = "nightly", feature(plugin))] - #![cfg_attr(feature = "lints", plugin(clippy))] #![cfg_attr(feature = "lints", deny(warnings))] #![cfg_attr(not(any(feature = "lints", feature = "nightly")), deny())] #![deny( -missing_debug_implementations, -missing_copy_implementations, -trivial_casts, -trivial_numeric_casts, -unused_import_braces, -unused_qualifications + missing_debug_implementations, + missing_copy_implementations, + trivial_casts, + trivial_numeric_casts, + unused_import_braces, + unused_qualifications )] //! ![uml](ml.svg) extern crate dot; extern crate itertools; +extern crate quote; extern crate syn; extern crate walkdir; -extern crate quote; use std::ffi::OsStr; use std::fs::{self, File}; @@ -37,12 +34,12 @@ use syn::parse_file; use walkdir::WalkDir; use core::ListItem; -use module::Module; use module::path::ModulePath; +use module::Module; -pub mod prelude; -pub mod module; pub mod core; +pub mod module; +pub mod prelude; /// The default name of *graph/dot* file. pub const DEFAULT_NAME_DOT: &str = "ml.dot"; @@ -60,8 +57,12 @@ impl std::fmt::Display for Error { let mut debug_struct = f.debug_struct("MlError"); match self { - Error::IoError(err) => { debug_struct.field("err", &err.to_string()); } - Error::SynError(err) => { debug_struct.field("err", &err.to_string()); } + Error::IoError(err) => { + debug_struct.field("err", &err.to_string()); + } + Error::SynError(err) => { + debug_struct.field("err", &err.to_string()); + } } debug_struct.finish() @@ -95,10 +96,10 @@ fn file2crate>(path: P) -> Result { /// The function `items2chars` returns a graph formated for *Graphiz/Dot*. fn items2chars(modules: Vec) -> Result, Error> { let mut f: Vec = Vec::new(); - let iter: Vec<(syn::Item, Rc)> = - modules.into_iter() - .flat_map(|s: Module| s.into_iter()) - .collect::)>>(); + let iter: Vec<(syn::Item, Rc)> = modules + .into_iter() + .flat_map(|s: Module| s.into_iter()) + .collect::)>>(); let iter: ListItem = ListItem::from(iter.iter().peekable()); dot::render(&iter, &mut f).map(|()| f).map_err(Into::into) @@ -115,7 +116,12 @@ fn items2chars(modules: Vec) -> Result, Error> { /// } /// ``` pub fn rs2dot>(path: P) -> Result, Error> { - file2crate(path.as_ref()).and_then(|parse: syn::File| items2chars(vec![Module::from((parse.items, path.as_ref().to_path_buf()))])) + file2crate(path.as_ref()).and_then(|parse: syn::File| { + items2chars(vec![Module::from(( + parse.items, + path.as_ref().to_path_buf(), + ))]) + }) } /// The function `src2dot` returns graphed repository of modules. @@ -129,33 +135,42 @@ pub fn rs2dot>(path: P) -> Result, Error> { /// } /// ``` pub fn src2dot>(path: P) -> Result, Error> { - items2chars(WalkDir::new(path).into_iter() - .filter_map(|entry: Result| entry.ok()) - .filter(|entry| entry.file_type().is_file()) - .filter_map(|entry: walkdir::DirEntry| { - let path: &Path = entry.path(); - - if path.extension().eq(&Some(OsStr::new("rs"))) { - file2crate(path).ok().map(|file| Module::from((file.items, path.to_path_buf()))) - } else { - None - } - }) - .collect::>()).map_err(Into::into) + items2chars( + WalkDir::new(path) + .into_iter() + .filter_map(|entry: Result| entry.ok()) + .filter(|entry| entry.file_type().is_file()) + .filter_map(|entry: walkdir::DirEntry| { + let path: &Path = entry.path(); + + if path.extension().eq(&Some(OsStr::new("rs"))) { + file2crate(path) + .ok() + .map(|file| Module::from((file.items, path.to_path_buf()))) + } else { + None + } + }) + .collect::>(), + ) + .map_err(Into::into) } /// The function `content2svg` returns structured vector graphics content of modules. pub fn content2svg(buf: Vec) -> Result, Error> { - Command::new("dot").arg("-Tsvg") - .stdin(Stdio::piped()).stdout(Stdio::piped()) - .spawn() - .map(|child| { - let mut ret = vec![]; + Command::new("dot") + .arg("-Tsvg") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .map(|child| { + let mut ret = vec![]; child.stdin.unwrap().write_all(buf.as_slice()).unwrap(); child.stdout.unwrap().read_to_end(&mut ret).unwrap(); ret - }).map_err(Into::into) + }) + .map_err(Into::into) } /// The function `rs2svg` returns structured vector graphics file modules. diff --git a/src/module/mod.rs b/src/module/mod.rs index ac955ea6..c9e375fd 100644 --- a/src/module/mod.rs +++ b/src/module/mod.rs @@ -1,6 +1,6 @@ -use std::rc::Rc; -use std::path::PathBuf; use std::ffi::OsString; +use std::path::PathBuf; +use std::rc::Rc; use std::vec; extern crate syn; @@ -21,10 +21,11 @@ impl From<(Vec, PathBuf)> for Module { Module { list, path: ModulePath { - path: path.components() - .skip(1) - .map(|comp| comp.as_os_str().to_os_string()) - .collect::>(), + path: path + .components() + .skip(1) + .map(|comp| comp.as_os_str().to_os_string()) + .collect::>(), }, } } @@ -36,9 +37,10 @@ impl IntoIterator for Module { fn into_iter(self) -> Self::IntoIter { let rc = &Rc::new(self.path); - self.list.into_iter() - .map(|item| (item, Rc::clone(rc))) - .collect::)>>() - .into_iter() + self.list + .into_iter() + .map(|item| (item, Rc::clone(rc))) + .collect::)>>() + .into_iter() } } diff --git a/src/prelude.rs b/src/prelude.rs index 4b26c19c..7912b6b0 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,15 +1,15 @@ //! The purpose of this module is to provide reexports of core traits so that they can be then //! glob-imported all at once. -pub use ::DEFAULT_NAME_DOT; -pub use ::DEFAULT_NAME_PNG; -pub use ::core::segment::Segment; -pub use ::core::item::Item; -pub use ::core::item::relation::Relation; -pub use ::core::item::state::ItemState; -pub use ::core::item::state::method::Method; -pub use ::core::item::state::implem::Implem; -pub use ::core::item::state::abstraction::Abstract; -pub use ::core::item::state::abstraction::extend::Trait; -pub use ::core::item::state::abstraction::structure::Struct; -pub use ::core::item::state::abstraction::enumerate::Enum; +pub use core::item::relation::Relation; +pub use core::item::state::abstraction::enumerate::Enum; +pub use core::item::state::abstraction::extend::Trait; +pub use core::item::state::abstraction::structure::Struct; +pub use core::item::state::abstraction::Abstract; +pub use core::item::state::implem::Implem; +pub use core::item::state::method::Method; +pub use core::item::state::ItemState; +pub use core::item::Item; +pub use core::segment::Segment; +pub use DEFAULT_NAME_DOT; +pub use DEFAULT_NAME_PNG; diff --git a/tests/aggregation.rs b/tests/aggregation.rs index 20459055..ac7ecfef 100644 --- a/tests/aggregation.rs +++ b/tests/aggregation.rs @@ -34,8 +34,14 @@ fn test_aggregation() { } } - File::create("target/test/aggregation/aggregation.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); - File::create("target/test/aggregation/aggregation_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + File::create("target/test/aggregation/aggregation.svg") + .unwrap() + .write(&mml::content2svg(vec.clone()).unwrap()) + .unwrap(); + File::create("target/test/aggregation/aggregation_target.svg") + .unwrap() + .write(&mml::content2svg(target.to_string().into_bytes()).unwrap()) + .unwrap(); assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/association.rs b/tests/association.rs index 120bc804..d4a23d00 100644 --- a/tests/association.rs +++ b/tests/association.rs @@ -1,9 +1,9 @@ #![allow(dead_code)] extern crate mml; -use std::path::Path; use std::fs::File; use std::io::Write; +use std::path::Path; struct A {} @@ -48,8 +48,14 @@ fn test_association() { } } - File::create("target/test/association/association.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); - File::create("target/test/association/association_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + File::create("target/test/association/association.svg") + .unwrap() + .write(&mml::content2svg(vec.clone()).unwrap()) + .unwrap(); + File::create("target/test/association/association_target.svg") + .unwrap() + .write(&mml::content2svg(target.to_string().into_bytes()).unwrap()) + .unwrap(); assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/composition.rs b/tests/composition.rs index 2b10ac9b..2cee4add 100644 --- a/tests/composition.rs +++ b/tests/composition.rs @@ -29,8 +29,14 @@ fn test_composition() { } } - File::create("target/test/composition/composition.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); - File::create("target/test/composition/composition_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + File::create("target/test/composition/composition.svg") + .unwrap() + .write(&mml::content2svg(vec.clone()).unwrap()) + .unwrap(); + File::create("target/test/composition/composition_target.svg") + .unwrap() + .write(&mml::content2svg(target.to_string().into_bytes()).unwrap()) + .unwrap(); assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/dependency.rs b/tests/dependency.rs index 9bb8a774..4c3e140b 100644 --- a/tests/dependency.rs +++ b/tests/dependency.rs @@ -2,8 +2,8 @@ extern crate mml; use std::fs::File; -use std::path::Path; use std::io::Write; +use std::path::Path; struct A {} @@ -30,8 +30,14 @@ fn test_dependency() { } } - File::create("target/test/dependency/dependency.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); - File::create("target/test/dependency/dependency_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + File::create("target/test/dependency/dependency.svg") + .unwrap() + .write(&mml::content2svg(vec.clone()).unwrap()) + .unwrap(); + File::create("target/test/dependency/dependency_target.svg") + .unwrap() + .write(&mml::content2svg(target.to_string().into_bytes()).unwrap()) + .unwrap(); assert_eq!(String::from_utf8(vec).unwrap(), target); } diff --git a/tests/realization.rs b/tests/realization.rs index 1f671133..9a662c04 100644 --- a/tests/realization.rs +++ b/tests/realization.rs @@ -7,25 +7,35 @@ use std::io::Write; use std::path::Path; #[derive(Debug)] -struct A where T: Debug { +struct A +where + T: Debug, +{ a: T, } -impl A where T: Debug { +impl A +where + T: Debug, +{ fn a(a: T) -> Self { - A { - a, - } + A { a } } } -impl B for A where T: Debug { +impl B for A +where + T: Debug, +{ fn a(&self) -> Option { None } } -trait B: Debug where T: Debug { +trait B: Debug +where + T: Debug, +{ fn a(&self) -> Option; } @@ -52,8 +62,14 @@ fn test_realization() { } } - File::create("target/test/realization/realization.svg").unwrap().write(&mml::content2svg(vec.clone()).unwrap()).unwrap(); - File::create("target/test/realization/realization_target.svg").unwrap().write(&mml::content2svg(target.to_string().into_bytes()).unwrap()).unwrap(); + File::create("target/test/realization/realization.svg") + .unwrap() + .write(&mml::content2svg(vec.clone()).unwrap()) + .unwrap(); + File::create("target/test/realization/realization_target.svg") + .unwrap() + .write(&mml::content2svg(target.to_string().into_bytes()).unwrap()) + .unwrap(); assert_eq!(String::from_utf8(vec).unwrap(), target); } From fbfcec9fcd65f97f735eb174355716908f535a73 Mon Sep 17 00:00:00 2001 From: Stefan Lukas Date: Sat, 30 Jan 2021 18:30:08 +0100 Subject: [PATCH 11/11] Disable CI on OSX --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 98241835..fbbb6826 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ rust: - beta - nightly os: - - osx + # - osx - linux addons: apt: @@ -28,4 +28,4 @@ script: travis-cargo run travis-cargo test travis-cargo bench - travis-cargo doc -- --no-deps \ No newline at end of file + travis-cargo doc -- --no-deps