Skip to content

Commit

Permalink
Minor cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
taiki-e committed May 4, 2020
1 parent c5899f4 commit 23e8a8f
Show file tree
Hide file tree
Showing 6 changed files with 246 additions and 255 deletions.
8 changes: 7 additions & 1 deletion core/src/auto_enum/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use proc_macro2::TokenStream;
use quote::format_ident;
use syn::{
parse::{Parse, ParseStream},
*,
Result, *,
};

use crate::utils::{expr_call, path, replace_expr, unit, VisitedNode};
Expand Down Expand Up @@ -67,6 +67,7 @@ pub(super) struct Context {
/// All marker macro identifiers that may have effects on the current scope.
pub(super) markers: Vec<String>,

// TODO: we may be able to replace some fields based on depth.
// depth: isize,
/// Currently, this is basically the same as `self.markers.len() == 1`.
root: bool,
Expand Down Expand Up @@ -129,10 +130,12 @@ impl Context {
})
}

/// Make a new `Context` as a root.
pub(super) fn root(span: TokenStream, args: TokenStream) -> Result<Self> {
Self::new(span, args, true, Vec::new(), Diagnostic::default())
}

/// Make a new `Context` as a child based on a parent context `self`.
pub(super) fn make_child(&mut self, span: TokenStream, args: TokenStream) -> Result<Self> {
Self::new(
span,
Expand All @@ -143,6 +146,7 @@ impl Context {
)
}

/// Merge a child `Context` into a parent context `self`.
pub(super) fn join_child(&mut self, mut child: Self) {
debug_assert!(self.diagnostic.messages.is_empty());
debug_assert!(self.markers.is_empty());
Expand Down Expand Up @@ -209,10 +213,12 @@ impl Context {
mac.path.is_ident(&self.marker)
}

/// from `<expr>` into `Enum::VariantN(<expr>)`
pub(super) fn next_expr(&mut self, expr: Expr) -> Expr {
self.next_expr_with_attrs(Vec::new(), expr)
}

/// from `<expr>` into `<attrs> Enum::VariantN(<expr>)`
pub(super) fn next_expr_with_attrs(&mut self, attrs: Vec<Attribute>, expr: Expr) -> Expr {
self.builder.next_expr(attrs, expr)
}
Expand Down
105 changes: 46 additions & 59 deletions core/src/auto_enum/expr.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use syn::{
visit_mut::{self, VisitMut},
*,
Result, *,
};

use crate::utils::{expr_block, replace_block, replace_expr, Attrs};
Expand All @@ -18,24 +18,22 @@ pub(super) fn child_expr(expr: &mut Expr, cx: &mut Context) -> Result<()> {
match expr {
Expr::Block(ExprBlock { block, .. }) | Expr::Unsafe(ExprUnsafe { block, .. }) => {
if let Some(Stmt::Expr(expr)) = block.stmts.last_mut() {
return child_expr(expr, cx);
child_expr(expr, cx)?;
}
}
_ => {}
}

match expr {
Expr::Match(expr) => visit_last_expr_match(cx, expr),
Expr::If(expr) => visit_last_expr_if(cx, expr),
Expr::Match(expr) => visit_last_expr_match(cx, expr)?,
Expr::If(expr) => visit_last_expr_if(cx, expr)?,
Expr::Loop(expr) => visit_last_expr_loop(cx, expr),

// Search recursively
Expr::MethodCall(ExprMethodCall { receiver: expr, .. })
| Expr::Paren(ExprParen { expr, .. })
| Expr::Type(ExprType { expr, .. }) => child_expr(expr, cx),
| Expr::Type(ExprType { expr, .. }) => child_expr(expr, cx)?,

_ => Ok(()),
_ => {}
}
Ok(())
}

pub(super) fn is_unreachable(cx: &Context, expr: &Expr) -> bool {
Expand Down Expand Up @@ -141,68 +139,57 @@ fn visit_last_expr_if(cx: &mut Context, expr: &mut ExprIf) -> Result<()> {
}
}

fn visit_last_expr_loop(cx: &mut Context, expr: &mut ExprLoop) -> Result<()> {
LoopVisitor::new(expr.label.as_ref(), cx).visit_block_mut(&mut expr.body);
Ok(())
}

// =================================================================================================
// LoopVisitor

struct LoopVisitor<'a> {
cx: &'a mut Context,
label: Option<&'a Label>,
nested: bool,
}

impl<'a> LoopVisitor<'a> {
fn new(label: Option<&'a Label>, cx: &'a mut Context) -> Self {
Self { cx, label, nested: false }
fn visit_last_expr_loop(cx: &mut Context, expr: &mut ExprLoop) {
struct LoopVisitor<'a> {
cx: &'a mut Context,
label: Option<&'a Label>,
nested: bool,
}

fn compare_labels(&self, other: Option<&Lifetime>) -> bool {
match (self.label, other) {
(None, None) => true,
(Some(this), Some(other)) => this.name.ident == other.ident,
_ => false,
impl LoopVisitor<'_> {
fn compare_labels(&self, other: Option<&Lifetime>) -> bool {
match (self.label, other) {
(None, None) => true,
(Some(this), Some(other)) => this.name.ident == other.ident,
_ => false,
}
}
}
}

impl VisitMut for LoopVisitor<'_> {
fn visit_expr_mut(&mut self, node: &mut Expr) {
if node.any_empty_attr(NEVER) {
return;
}

let tmp = self.nested;
match node {
// Stop at closure / async block bounds
Expr::Closure(_) | Expr::Async(_) => return,

// Other loop bounds
Expr::Loop(_) | Expr::ForLoop(_) | Expr::While(_) => {
if self.label.is_none() {
return;
}
self.nested = true;
impl VisitMut for LoopVisitor<'_> {
fn visit_expr_mut(&mut self, node: &mut Expr) {
if node.any_empty_attr(NEVER) {
return;
}

// Desugar `break <expr>` into `break Enum::VariantN(<expr>)`.
Expr::Break(ExprBreak { label, expr, .. }) => {
if !self.nested && label.is_none() || self.compare_labels(label.as_ref()) {
self.cx.replace_boxed_expr(expr);
let tmp = self.nested;
match node {
// Stop at closure / async block bounds
Expr::Closure(_) | Expr::Async(_) => return,
// Other loop bounds
Expr::Loop(_) | Expr::ForLoop(_) | Expr::While(_) => {
if self.label.is_none() {
return;
}
self.nested = true;
}
// Desugar `break <expr>` into `break Enum::VariantN(<expr>)`.
Expr::Break(ExprBreak { label, expr, .. }) => {
if !self.nested && label.is_none() || self.compare_labels(label.as_ref()) {
self.cx.replace_boxed_expr(expr);
}
}
_ => {}
}

_ => {}
visit_mut::visit_expr_mut(self, node);
self.nested = tmp;
}

visit_mut::visit_expr_mut(self, node);
self.nested = tmp;
fn visit_item_mut(&mut self, _: &mut Item) {
// Do not recurse into nested items.
}
}

fn visit_item_mut(&mut self, _: &mut Item) {
// Do not recurse into nested items.
}
LoopVisitor { cx, label: expr.label.as_ref(), nested: false }.visit_block_mut(&mut expr.body);
}
22 changes: 11 additions & 11 deletions core/src/auto_enum/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use proc_macro2::TokenStream;
use quote::ToTokens;
use syn::*;

use crate::utils::*;
use crate::utils::{block, expr_block, replace_expr};

mod context;
mod expr;
Expand Down Expand Up @@ -48,14 +48,14 @@ pub(crate) fn attribute(args: TokenStream, input: TokenStream) -> TokenStream {
cx.diagnostic.to_compile_error().unwrap()
}

fn visit_expr(expr: &mut Expr, cx: &mut Context) -> Result<()> {
fn expand_expr(expr: &mut Expr, cx: &mut Context) -> Result<()> {
let expr = match expr {
Expr::Closure(ExprClosure { body, .. }) if cx.visit_last() => {
let (count_try, count_return) = visitor::visit_fn(cx, &mut **body);
if count_try >= 2 {
let count = visitor::visit_fn(cx, &mut **body);
if count.try_ >= 2 {
cx.visit_mode = VisitMode::Try;
} else {
cx.visit_mode = VisitMode::Return(count_return);
cx.visit_mode = VisitMode::Return(count.return_);
}
&mut **body
}
Expand Down Expand Up @@ -108,7 +108,7 @@ fn expand_parent_expr(expr: &mut Expr, cx: &mut Context, has_semi: bool) -> Resu
return Ok(());
}

visit_expr(expr, cx)?;
expand_expr(expr, cx)?;

cx.build(|item| build_expr(expr, item))
}
Expand All @@ -135,7 +135,7 @@ fn expand_parent_local(local: &mut Local, cx: &mut Context) -> Result<()> {
));
};

visit_expr(expr, cx)?;
expand_expr(expr, cx)?;

cx.build(|item| build_expr(expr, item))
}
Expand All @@ -149,8 +149,8 @@ fn expand_parent_item_fn(item: &mut ItemFn, cx: &mut Context) -> Result<()> {
match &**ty {
// `return`
Type::ImplTrait(_) if cx.visit_last_mode != VisitLastMode::Never => {
let (_, count_return) = visitor::visit_fn(cx, &mut **block);
cx.visit_mode = VisitMode::Return(count_return);
let count = visitor::visit_fn(cx, &mut **block);
cx.visit_mode = VisitMode::Return(count.return_);
}

// `?` operator
Expand All @@ -170,8 +170,8 @@ fn expand_parent_item_fn(item: &mut ItemFn, cx: &mut Context) -> Result<()> {
GenericArgument::Type(Type::ImplTrait(_)),
) = (&args[0], &args[1])
{
let (count_try, _) = visitor::visit_fn(cx, &mut **block);
if count_try >= 2 {
let count = visitor::visit_fn(cx, &mut **block);
if count.try_ >= 2 {
cx.visit_mode = VisitMode::Try;
}
}
Expand Down
42 changes: 18 additions & 24 deletions core/src/auto_enum/type_analysis.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,33 @@
use quote::ToTokens;
use syn::{
visit_mut::{self, VisitMut},
*,
Path, Type, TypeImplTrait, TypeParamBound,
};

use crate::utils::*;
use crate::utils::path;

pub(super) fn collect_impl_trait(args: &[Path], traits: &mut Vec<Path>, ty: &mut Type) {
CollectImplTrait::new(args, traits).visit_type_mut(ty);
}

struct CollectImplTrait<'a> {
args: &'a [Path],
traits: &'a mut Vec<Path>,
}

impl<'a> CollectImplTrait<'a> {
fn new(args: &'a [Path], traits: &'a mut Vec<Path>) -> Self {
Self { args, traits }
struct CollectImplTrait<'a> {
args: &'a [Path],
traits: &'a mut Vec<Path>,
}
}

impl VisitMut for CollectImplTrait<'_> {
fn visit_type_impl_trait_mut(&mut self, node: &mut TypeImplTrait) {
visit_mut::visit_type_impl_trait_mut(self, node);
impl VisitMut for CollectImplTrait<'_> {
fn visit_type_impl_trait_mut(&mut self, node: &mut TypeImplTrait) {
visit_mut::visit_type_impl_trait_mut(self, node);

node.bounds.iter().for_each(|ty| {
if let TypeParamBound::Trait(ty) = ty {
let ty = path(ty.path.segments.iter().map(|ty| ty.ident.clone().into()));
if !self.args.contains(&ty) && TRAITS.contains(&&*to_trimed_string(&ty)) {
self.traits.push(ty);
node.bounds.iter().for_each(|ty| {
if let TypeParamBound::Trait(ty) = ty {
let ty = path(ty.path.segments.iter().map(|ty| ty.ident.clone().into()));
if !self.args.contains(&ty) && TRAITS.contains(&&*to_trimed_string(&ty)) {
self.traits.push(ty);
}
}
}
});
});
}
}

CollectImplTrait { args, traits }.visit_type_mut(ty);
}

fn to_trimed_string(path: &Path) -> String {
Expand Down
Loading

0 comments on commit 23e8a8f

Please sign in to comment.