<commit_before>use futures::{self, Future};
use futures::future::lazy;
use ::*;

/// Basic test of using futures to data on the stack frame.
#[test]
fn future_test() {
    let data = &[0, 1];

    // Here we call `wait` on a select future, which will block at
    // least one thread. So we need a second thread to ensure no
    // deadlock.
    ThreadPool::new(Configuration::new().set_num_threads(2)).unwrap().install(|| {
        scope(|s| {
            let a = s.spawn_future(futures::future::ok::<_, ()>(&data[0]));
            let b = s.spawn_future(futures::future::ok::<_, ()>(&data[1]));
            let (item1, next) = a.select(b).wait().ok().unwrap();
            let item2 = next.wait().unwrap();
            assert!(*item1 == 0 || *item1 == 1);
            assert!(*item2 == 1 - *item1);
        });
    });
}

/// Test using `map` on a Rayon future. The `map` closure is eecuted
/// for side-effects, and modifies the `data` variable that is owned
/// by enclosing stack frame.
#[test]
fn future_map() {
    let data = &mut [format!("Hello, ")];

    let mut future = None;
    scope(|s| {
        let a = s.spawn_future(lazy(|| Ok::<_, ()>(&mut data[0])));
        future = Some(s.spawn_future(a.map(|v| {
            v.push_str("world!");
        })));
    });

    // future must have executed for the scope to have ended, even
    // though we never invoked `wait` to observe its result
    assert_eq!(data[0], "Hello, world!");
    assert!(future.is_some());
}

/// Test that we can create a future that returns an `&mut` to data,
/// so long as it outlives the scope.
#[test]
fn future_escape_ref() {
    let data = &mut [format!("Hello, ")];

    {
        let mut future = None;
        scope(|s| {
            let data = &mut *data;
            future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
        });
        let s = future.unwrap().wait().unwrap();
        s.push_str("world!");
    }

    assert_eq!(data[0], "Hello, world!");
}

#[test]
#[should_panic]
fn future_panic_prop() {
    scope(|s| {
        let future = s.spawn_future(lazy(move || Ok::<(), ()>(argh())));
        let _ = future.rayon_wait(); // should panic, not return a value
    });

    fn argh() -> () {
        if true {
            panic!("Hello, world!");
        }
    }
}

/// Test that, even if we have only one thread, invoke `rayon_wait`
/// will not panic.
#[test]
fn future_rayon_wait_1_thread() {
    // run with only 1 worker thread; this would deadlock if we couldn't make progress
    let mut result = None;
    ThreadPool::new(Configuration::new().set_num_threads(1)).unwrap().install(|| {
        scope(|s| {
            use std::sync::mpsc::channel;
            let (tx, rx) = channel();
            let a = s.spawn_future(lazy(move || Ok::<usize, ()>(rx.recv().unwrap())));
            //                          ^^^^ FIXME: why is this needed?
            let b = s.spawn_future(a.map(|v| v + 1));
            let c = s.spawn_future(b.map(|v| v + 1));
            s.spawn(move |_| tx.send(20).unwrap());
            result = Some(c.rayon_wait().unwrap());
        });
    });
    assert_eq!(result, Some(22));
}

/// Test that invoking `wait` on a `RayonFuture` will panic, if it is inside
/// a Rayon worker thread.
#[test]
#[should_panic]
fn future_wait_panics_inside_rayon_thread() {
    scope(|s| {
        let future = s.spawn_future(lazy(move || Ok::<(), ()>(())));
        let _ = future.wait(); // should panic, not return a value
    });
}

/// Test that invoking `wait` on a `RayonFuture` will not panic if we
/// are outside a Rayon worker thread.
#[test]
fn future_wait_works_outside_rayon_threads() {
    let mut future = None;
    scope(|s| {
        future = Some(s.spawn_future(lazy(move || Ok::<(), ()>(()))));
    });
    assert_eq!(Ok(()), future.unwrap().wait());
}

<commit_msg>avoid ::* for 1.12 compat<commit_after>use futures::{self, Future};
use futures::future::lazy;
use ::{scope, ThreadPool, Configuration};

/// Basic test of using futures to data on the stack frame.
#[test]
fn future_test() {
    let data = &[0, 1];

    // Here we call `wait` on a select future, which will block at
    // least one thread. So we need a second thread to ensure no
    // deadlock.
    ThreadPool::new(Configuration::new().set_num_threads(2)).unwrap().install(|| {
        scope(|s| {
            let a = s.spawn_future(futures::future::ok::<_, ()>(&data[0]));
            let b = s.spawn_future(futures::future::ok::<_, ()>(&data[1]));
            let (item1, next) = a.select(b).wait().ok().unwrap();
            let item2 = next.wait().unwrap();
            assert!(*item1 == 0 || *item1 == 1);
            assert!(*item2 == 1 - *item1);
        });
    });
}

/// Test using `map` on a Rayon future. The `map` closure is eecuted
/// for side-effects, and modifies the `data` variable that is owned
/// by enclosing stack frame.
#[test]
fn future_map() {
    let data = &mut [format!("Hello, ")];

    let mut future = None;
    scope(|s| {
        let a = s.spawn_future(lazy(|| Ok::<_, ()>(&mut data[0])));
        future = Some(s.spawn_future(a.map(|v| {
            v.push_str("world!");
        })));
    });

    // future must have executed for the scope to have ended, even
    // though we never invoked `wait` to observe its result
    assert_eq!(data[0], "Hello, world!");
    assert!(future.is_some());
}

/// Test that we can create a future that returns an `&mut` to data,
/// so long as it outlives the scope.
#[test]
fn future_escape_ref() {
    let data = &mut [format!("Hello, ")];

    {
        let mut future = None;
        scope(|s| {
            let data = &mut *data;
            future = Some(s.spawn_future(lazy(move || Ok::<_, ()>(&mut data[0]))));
        });
        let s = future.unwrap().wait().unwrap();
        s.push_str("world!");
    }

    assert_eq!(data[0], "Hello, world!");
}

#[test]
#[should_panic]
fn future_panic_prop() {
    scope(|s| {
        let future = s.spawn_future(lazy(move || Ok::<(), ()>(argh())));
        let _ = future.rayon_wait(); // should panic, not return a value
    });

    fn argh() -> () {
        if true {
            panic!("Hello, world!");
        }
    }
}

/// Test that, even if we have only one thread, invoke `rayon_wait`
/// will not panic.
#[test]
fn future_rayon_wait_1_thread() {
    // run with only 1 worker thread; this would deadlock if we couldn't make progress
    let mut result = None;
    ThreadPool::new(Configuration::new().set_num_threads(1)).unwrap().install(|| {
        scope(|s| {
            use std::sync::mpsc::channel;
            let (tx, rx) = channel();
            let a = s.spawn_future(lazy(move || Ok::<usize, ()>(rx.recv().unwrap())));
            //                          ^^^^ FIXME: why is this needed?
            let b = s.spawn_future(a.map(|v| v + 1));
            let c = s.spawn_future(b.map(|v| v + 1));
            s.spawn(move |_| tx.send(20).unwrap());
            result = Some(c.rayon_wait().unwrap());
        });
    });
    assert_eq!(result, Some(22));
}

/// Test that invoking `wait` on a `RayonFuture` will panic, if it is inside
/// a Rayon worker thread.
#[test]
#[should_panic]
fn future_wait_panics_inside_rayon_thread() {
    scope(|s| {
        let future = s.spawn_future(lazy(move || Ok::<(), ()>(())));
        let _ = future.wait(); // should panic, not return a value
    });
}

/// Test that invoking `wait` on a `RayonFuture` will not panic if we
/// are outside a Rayon worker thread.
#[test]
fn future_wait_works_outside_rayon_threads() {
    let mut future = None;
    scope(|s| {
        future = Some(s.spawn_future(lazy(move || Ok::<(), ()>(()))));
    });
    assert_eq!(Ok(()), future.unwrap().wait());
}

<|endoftext|>


<commit_before>extern crate find_folder;

use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window) }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input, window: &piston_window::PistonWindow) -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(200.)
                .pad(30.0)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Text::new("Widget Demonstration")
                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .font_size(32)
                .color(conrod::color::rgb(0.2, 0.35, 0.45).plain_contrast())
                .set(TITLE, ui);
        });

        window.draw_2d(|context, graphics| self.ui.draw(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {}
}

widget_ids! {
    CANVAS,
    TITLE,
}

fn create_ui(window: &piston_window::PistonWindow) -> conrod::Ui<piston_window::Glyphs> {
    let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
    let font_path = assets.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<commit_msg>set_widgets has been moved to on_update<commit_after>extern crate find_folder;

use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window) }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self, input: &piston_window::Input, window: &piston_window::PistonWindow) -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        self.ui.set_widgets(|ui| {
            conrod::Canvas::new()
                .frame(200.)
                .pad(30.0)
                .color(conrod::color::rgb(0.2, 0.35, 0.45))
                .scroll_kids()
                .set(CANVAS, ui);

            conrod::Text::new("Widget Demonstration")
                .top_left_with_margins_on(CANVAS, 0.0, 350.0)
                .font_size(32)
                .color(conrod::color::rgb(0.2, 0.35, 0.45).plain_contrast())
                .set(TITLE, ui);
        });
    }
}

widget_ids! {
    CANVAS,
    TITLE,
}

fn create_ui(window: &piston_window::PistonWindow) -> conrod::Ui<piston_window::Glyphs> {
    let assets = find_folder::Search::KidsThenParents(3, 5).for_folder("assets").unwrap();
    let font_path = assets.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}
<|endoftext|>


<commit_before>use crate::source_analysis::prelude::*;
use syn::*;

pub(crate) fn check_attr_list(
    attrs: &[Attribute],
    ctx: &Context,
    analysis: &mut LineAnalysis,
) -> bool {
    let mut check_cover = true;
    for attr in attrs {
        analysis.ignore_tokens(attr);
        if let Ok(x) = attr.parse_meta() {
            if check_cfg_attr(&x) {
                check_cover = false;
            } else if x.path().is_ident("cfg") {
                match x {
                    Meta::List(ref ml) => {
                        let mut skip = false;
                        for c in &ml.nested {
                            if let NestedMeta::Meta(Meta::Path(ref i)) = c {
                                skip |= i.is_ident("test") && ctx.config.ignore_tests;
                            }
                        }
                        if skip {
                            check_cover = false;
                        }
                    }
                    _ => {}
                }
            }
        }
        if !check_cover {
            break;
        }
    }
    check_cover
}

pub(crate) fn check_cfg_attr(attr: &Meta) -> bool {
    let mut ignore_span = false;
    let id = attr.path();
    if id.is_ident("cfg") {
        if let Meta::List(ml) = attr {
            'outer: for p in ml.nested.iter() {
                match p {
                    NestedMeta::Meta(Meta::List(ref i)) => {
                        if i.path.is_ident("not") {
                            for n in i.nested.iter() {
                                if let NestedMeta::Meta(Meta::Path(ref pth)) = n {
                                    if pth.is_ident("tarpaulin_include") || pth.is_ident("tarpaulin") {
                                        ignore_span = true;
                                        break 'outer;
                                    }
                                }
                            }
                        }
                    }
                    _ => {}
                }
            }
        }
    } else {
        let skip_attrs = vec!["tarpaulin", "skip"];
        let mut n = 0;
        ignore_span = true;
        for (segment, attr) in id.segments.iter().zip(skip_attrs.iter()) {
            n += 1;
            if segment.ident != attr {
                ignore_span = false;
            }
        }
        if n < skip_attrs.len() {
            ignore_span = false;
        }
    }
    ignore_span
}
<commit_msg>Cargo fmt<commit_after>use crate::source_analysis::prelude::*;
use syn::*;

pub(crate) fn check_attr_list(
    attrs: &[Attribute],
    ctx: &Context,
    analysis: &mut LineAnalysis,
) -> bool {
    let mut check_cover = true;
    for attr in attrs {
        analysis.ignore_tokens(attr);
        if let Ok(x) = attr.parse_meta() {
            if check_cfg_attr(&x) {
                check_cover = false;
            } else if x.path().is_ident("cfg") {
                match x {
                    Meta::List(ref ml) => {
                        let mut skip = false;
                        for c in &ml.nested {
                            if let NestedMeta::Meta(Meta::Path(ref i)) = c {
                                skip |= i.is_ident("test") && ctx.config.ignore_tests;
                            }
                        }
                        if skip {
                            check_cover = false;
                        }
                    }
                    _ => {}
                }
            }
        }
        if !check_cover {
            break;
        }
    }
    check_cover
}

pub(crate) fn check_cfg_attr(attr: &Meta) -> bool {
    let mut ignore_span = false;
    let id = attr.path();
    if id.is_ident("cfg") {
        if let Meta::List(ml) = attr {
            'outer: for p in ml.nested.iter() {
                match p {
                    NestedMeta::Meta(Meta::List(ref i)) => {
                        if i.path.is_ident("not") {
                            for n in i.nested.iter() {
                                if let NestedMeta::Meta(Meta::Path(ref pth)) = n {
                                    if pth.is_ident("tarpaulin_include")
                                        || pth.is_ident("tarpaulin")
                                    {
                                        ignore_span = true;
                                        break 'outer;
                                    }
                                }
                            }
                        }
                    }
                    _ => {}
                }
            }
        }
    } else {
        let skip_attrs = vec!["tarpaulin", "skip"];
        let mut n = 0;
        ignore_span = true;
        for (segment, attr) in id.segments.iter().zip(skip_attrs.iter()) {
            n += 1;
            if segment.ident != attr {
                ignore_span = false;
            }
        }
        if n < skip_attrs.len() {
            ignore_span = false;
        }
    }
    ignore_span
}
<|endoftext|>


<commit_before>use ra_db::FileId;
use ra_syntax::{
    SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast,
    SyntaxKind::{self, NAME},
};
use hir::{ModuleSource, FieldSource, Name};

use crate::{FileSymbol, db::RootDatabase};

/// `NavigationTarget` represents and element in the editor's UI which you can
/// click on to navigate to a particular piece of code.
///
/// Typically, a `NavigationTarget` corresponds to some element in the source
/// code, like a function or a struct, but this is not strictly required.
#[derive(Debug, Clone)]
pub struct NavigationTarget {
    file_id: FileId,
    name: SmolStr,
    kind: SyntaxKind,
    full_range: TextRange,
    focus_range: Option<TextRange>,
    container_name: Option<SmolStr>,
}

impl NavigationTarget {
    pub fn name(&self) -> &SmolStr {
        &self.name
    }

    pub fn container_name(&self) -> Option<&SmolStr> {
        self.container_name.as_ref()
    }

    pub fn kind(&self) -> SyntaxKind {
        self.kind
    }

    pub fn file_id(&self) -> FileId {
        self.file_id
    }

    pub fn full_range(&self) -> TextRange {
        self.full_range
    }

    /// A "most interesting" range withing the `range_full`.
    ///
    /// Typically, `range` is the whole syntax node, including doc comments, and
    /// `focus_range` is the range of the identifier.
    pub fn focus_range(&self) -> Option<TextRange> {
        self.focus_range
    }

    pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
        NavigationTarget {
            file_id: symbol.file_id,
            name: symbol.name.clone(),
            kind: symbol.ptr.kind(),
            full_range: symbol.ptr.range(),
            focus_range: None,
            container_name: symbol.container_name.map(|v| v.clone()),
        }
    }

    pub(crate) fn from_scope_entry(
        file_id: FileId,
        name: Name,
        ptr: SyntaxNodePtr,
    ) -> NavigationTarget {
        NavigationTarget {
            file_id,
            name: name.to_string().into(),
            full_range: ptr.range(),
            focus_range: None,
            kind: NAME,
            container_name: None,
        }
    }

    pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
        let (file_id, source) = module.definition_source(db);
        let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        match source {
            ModuleSource::SourceFile(node) => {
                NavigationTarget::from_syntax(file_id, name, None, node.syntax())
            }
            ModuleSource::Module(node) => {
                NavigationTarget::from_syntax(file_id, name, None, node.syntax())
            }
        }
    }

    pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
        let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        if let Some((file_id, source)) = module.declaration_source(db) {
            return NavigationTarget::from_syntax(file_id, name, None, source.syntax());
        }
        NavigationTarget::from_module(db, module)
    }

    pub(crate) fn from_function(db: &RootDatabase, func: hir::Function) -> NavigationTarget {
        let (file_id, fn_def) = func.source(db);
        NavigationTarget::from_named(file_id.original_file(db), &*fn_def)
    }

    pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget {
        let (file_id, field) = field.source(db);
        let file_id = file_id.original_file(db);
        match field {
            FieldSource::Named(it) => NavigationTarget::from_named(file_id, &*it),
            FieldSource::Pos(it) => {
                NavigationTarget::from_syntax(file_id, "".into(), None, it.syntax())
            }
        }
    }

    pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget {
        match module_def {
            hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module),
            hir::ModuleDef::Function(func) => NavigationTarget::from_function(db, func),
            hir::ModuleDef::Struct(s) => {
                let (file_id, node) = s.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Const(s) => {
                let (file_id, node) = s.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Static(s) => {
                let (file_id, node) = s.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Enum(e) => {
                let (file_id, node) = e.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::EnumVariant(var) => {
                let (file_id, node) = var.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Trait(e) => {
                let (file_id, node) = e.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Type(e) => {
                let (file_id, node) = e.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
        }
    }

    pub(crate) fn from_impl_block(
        db: &RootDatabase,
        module: hir::Module,
        impl_block: &hir::ImplBlock,
    ) -> NavigationTarget {
        let (file_id, _) = module.definition_source(db);
        let node = module.impl_source(db, impl_block.id());
        NavigationTarget::from_syntax(file_id, "impl".into(), None, node.syntax())
    }

    #[cfg(test)]
    pub(crate) fn assert_match(&self, expected: &str) {
        let actual = self.debug_render();
        test_utils::assert_eq_text!(expected.trim(), actual.trim(),);
    }

    #[cfg(test)]
    pub(crate) fn debug_render(&self) -> String {
        let mut buf = format!(
            "{} {:?} {:?} {:?}",
            self.name(),
            self.kind(),
            self.file_id(),
            self.full_range()
        );
        if let Some(focus_range) = self.focus_range() {
            buf.push_str(&format!(" {:?}", focus_range))
        }
        if let Some(container_name) = self.container_name() {
            buf.push_str(&format!(" {:?}", container_name))
        }
        buf
    }

    fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget {
        let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
        let focus_range = node.name().map(|it| it.syntax().range());
        NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax())
    }

    fn from_syntax(
        file_id: FileId,
        name: SmolStr,
        focus_range: Option<TextRange>,
        node: &SyntaxNode,
    ) -> NavigationTarget {
        NavigationTarget {
            file_id,
            name,
            kind: node.kind(),
            full_range: node.range(),
            focus_range,
            // ptr: Some(LocalSyntaxPtr::new(node)),
            container_name: None,
        }
    }
}
<commit_msg>Use clone directly rather than map + clone<commit_after>use ra_db::FileId;
use ra_syntax::{
    SyntaxNode, SyntaxNodePtr, AstNode, SmolStr, TextRange, ast,
    SyntaxKind::{self, NAME},
};
use hir::{ModuleSource, FieldSource, Name};

use crate::{FileSymbol, db::RootDatabase};

/// `NavigationTarget` represents and element in the editor's UI which you can
/// click on to navigate to a particular piece of code.
///
/// Typically, a `NavigationTarget` corresponds to some element in the source
/// code, like a function or a struct, but this is not strictly required.
#[derive(Debug, Clone)]
pub struct NavigationTarget {
    file_id: FileId,
    name: SmolStr,
    kind: SyntaxKind,
    full_range: TextRange,
    focus_range: Option<TextRange>,
    container_name: Option<SmolStr>,
}

impl NavigationTarget {
    pub fn name(&self) -> &SmolStr {
        &self.name
    }

    pub fn container_name(&self) -> Option<&SmolStr> {
        self.container_name.as_ref()
    }

    pub fn kind(&self) -> SyntaxKind {
        self.kind
    }

    pub fn file_id(&self) -> FileId {
        self.file_id
    }

    pub fn full_range(&self) -> TextRange {
        self.full_range
    }

    /// A "most interesting" range withing the `range_full`.
    ///
    /// Typically, `range` is the whole syntax node, including doc comments, and
    /// `focus_range` is the range of the identifier.
    pub fn focus_range(&self) -> Option<TextRange> {
        self.focus_range
    }

    pub(crate) fn from_symbol(symbol: FileSymbol) -> NavigationTarget {
        NavigationTarget {
            file_id: symbol.file_id,
            name: symbol.name.clone(),
            kind: symbol.ptr.kind(),
            full_range: symbol.ptr.range(),
            focus_range: None,
            container_name: symbol.container_name.clone(),
        }
    }

    pub(crate) fn from_scope_entry(
        file_id: FileId,
        name: Name,
        ptr: SyntaxNodePtr,
    ) -> NavigationTarget {
        NavigationTarget {
            file_id,
            name: name.to_string().into(),
            full_range: ptr.range(),
            focus_range: None,
            kind: NAME,
            container_name: None,
        }
    }

    pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
        let (file_id, source) = module.definition_source(db);
        let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        match source {
            ModuleSource::SourceFile(node) => {
                NavigationTarget::from_syntax(file_id, name, None, node.syntax())
            }
            ModuleSource::Module(node) => {
                NavigationTarget::from_syntax(file_id, name, None, node.syntax())
            }
        }
    }

    pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
        let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
        if let Some((file_id, source)) = module.declaration_source(db) {
            return NavigationTarget::from_syntax(file_id, name, None, source.syntax());
        }
        NavigationTarget::from_module(db, module)
    }

    pub(crate) fn from_function(db: &RootDatabase, func: hir::Function) -> NavigationTarget {
        let (file_id, fn_def) = func.source(db);
        NavigationTarget::from_named(file_id.original_file(db), &*fn_def)
    }

    pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget {
        let (file_id, field) = field.source(db);
        let file_id = file_id.original_file(db);
        match field {
            FieldSource::Named(it) => NavigationTarget::from_named(file_id, &*it),
            FieldSource::Pos(it) => {
                NavigationTarget::from_syntax(file_id, "".into(), None, it.syntax())
            }
        }
    }

    pub(crate) fn from_def(db: &RootDatabase, module_def: hir::ModuleDef) -> NavigationTarget {
        match module_def {
            hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module),
            hir::ModuleDef::Function(func) => NavigationTarget::from_function(db, func),
            hir::ModuleDef::Struct(s) => {
                let (file_id, node) = s.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Const(s) => {
                let (file_id, node) = s.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Static(s) => {
                let (file_id, node) = s.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Enum(e) => {
                let (file_id, node) = e.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::EnumVariant(var) => {
                let (file_id, node) = var.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Trait(e) => {
                let (file_id, node) = e.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
            hir::ModuleDef::Type(e) => {
                let (file_id, node) = e.source(db);
                NavigationTarget::from_named(file_id.original_file(db), &*node)
            }
        }
    }

    pub(crate) fn from_impl_block(
        db: &RootDatabase,
        module: hir::Module,
        impl_block: &hir::ImplBlock,
    ) -> NavigationTarget {
        let (file_id, _) = module.definition_source(db);
        let node = module.impl_source(db, impl_block.id());
        NavigationTarget::from_syntax(file_id, "impl".into(), None, node.syntax())
    }

    #[cfg(test)]
    pub(crate) fn assert_match(&self, expected: &str) {
        let actual = self.debug_render();
        test_utils::assert_eq_text!(expected.trim(), actual.trim(),);
    }

    #[cfg(test)]
    pub(crate) fn debug_render(&self) -> String {
        let mut buf = format!(
            "{} {:?} {:?} {:?}",
            self.name(),
            self.kind(),
            self.file_id(),
            self.full_range()
        );
        if let Some(focus_range) = self.focus_range() {
            buf.push_str(&format!(" {:?}", focus_range))
        }
        if let Some(container_name) = self.container_name() {
            buf.push_str(&format!(" {:?}", container_name))
        }
        buf
    }

    fn from_named(file_id: FileId, node: &impl ast::NameOwner) -> NavigationTarget {
        let name = node.name().map(|it| it.text().clone()).unwrap_or_default();
        let focus_range = node.name().map(|it| it.syntax().range());
        NavigationTarget::from_syntax(file_id, name, focus_range, node.syntax())
    }

    fn from_syntax(
        file_id: FileId,
        name: SmolStr,
        focus_range: Option<TextRange>,
        node: &SyntaxNode,
    ) -> NavigationTarget {
        NavigationTarget {
            file_id,
            name,
            kind: node.kind(),
            full_range: node.range(),
            focus_range,
            // ptr: Some(LocalSyntaxPtr::new(node)),
            container_name: None,
        }
    }
}
<|endoftext|>


<commit_before>use point::Point;

#[derive(Debug, Hash, Eq, PartialEq)]
pub struct Rectangle {
    pub top_left: Point<i16>,
    pub bottom_right: Point<i16>,
}

impl Rectangle {
    pub fn new(top_left: Point<i16>, (width, height): (u8, u8)) -> Rectangle {
        Rectangle {
            top_left: top_left,
            bottom_right: Point {
                x: top_left.x + width as i16,
                y: top_left.y + height as i16,
            }
        }
    }

    pub fn centre(&self) -> Point<i16> {
        Point {
            x: ((self.top_left.x + self.bottom_right.x) / 2),
            y: ((self.top_left.y + self.bottom_right.y) / 2),
        }
    }

    pub fn is_intersecting(&self, other: &Rectangle) -> bool {
        self.top_left.x <= other.bottom_right.x && self.bottom_right.x >= other.top_left.x
            && self.top_left.y <= other.bottom_right.y && self.bottom_right.y >= other.top_left.y
    }

    pub fn clamp_to(&mut self, (left, top): (i16, i16), (right, bottom): (i16, i16)) {
        if self.top_left.x < left {
            let diff = left - self.top_left.x;
            self.top_left.x += diff;
            self.bottom_right.x += diff;
        }
        if self.top_left.y < top {
            let diff = top - self.top_left.y;
            self.top_left.y += diff;
            self.bottom_right.y += diff;
        }

        if self.bottom_right.x > right {
            let diff = right - self.bottom_right.x;
            self.top_left.x += diff;
            self.bottom_right.x += diff;
        }
        if self.bottom_right.y > bottom {
            let diff = bottom - self.bottom_right.y;
            self.top_left.y += diff;
            self.bottom_right.y += diff;
        }
    }
}<commit_msg>Added method to get random point in rectangle.<commit_after>use rand;
use rand::Rng;

use point::Point;

#[derive(Debug, Hash, Eq, PartialEq)]
pub struct Rectangle {
    pub top_left: Point<i16>,
    pub bottom_right: Point<i16>,
}

impl Rectangle {
    pub fn new(top_left: Point<i16>, (width, height): (u8, u8)) -> Rectangle {
        Rectangle {
            top_left: top_left,
            bottom_right: Point {
                x: top_left.x + width as i16,
                y: top_left.y + height as i16,
            }
        }
    }

    pub fn centre(&self) -> Point<i16> {
        Point {
            x: ((self.top_left.x + self.bottom_right.x) / 2),
            y: ((self.top_left.y + self.bottom_right.y) / 2),
        }
    }

    pub fn get_random_position(&self, rng: &mut rand::ThreadRng) -> Point<i16> {
        Point {
            x: rng.gen_range(self.top_left.x+1, self.bottom_right.x),
            y: rng.gen_range(self.top_left.y+1, self.bottom_right.y),
        }
    }

    pub fn is_intersecting(&self, other: &Rectangle) -> bool {
        self.top_left.x <= other.bottom_right.x && self.bottom_right.x >= other.top_left.x
            && self.top_left.y <= other.bottom_right.y && self.bottom_right.y >= other.top_left.y
    }

    pub fn clamp_to(&mut self, (left, top): (i16, i16), (right, bottom): (i16, i16)) {
        if self.top_left.x < left {
            let diff = left - self.top_left.x;
            self.top_left.x += diff;
            self.bottom_right.x += diff;
        }
        if self.top_left.y < top {
            let diff = top - self.top_left.y;
            self.top_left.y += diff;
            self.bottom_right.y += diff;
        }

        if self.bottom_right.x > right {
            let diff = right - self.bottom_right.x;
            self.top_left.x += diff;
            self.bottom_right.x += diff;
        }
        if self.bottom_right.y > bottom {
            let diff = bottom - self.bottom_right.y;
            self.top_left.y += diff;
            self.bottom_right.y += diff;
        }
    }
}<|endoftext|>


<commit_before>extern crate crossbeam;
extern crate walkdir;

pub mod single_threaded;

use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::fs;
use self::crossbeam::sync::chase_lev;
use self::walkdir::WalkDir;
use regex::{RegexSet, Regex};
use std::path::PathBuf;
use colored::*;
use std::process::exit;
use utils::size;
use std::thread;
use error::*;
use types::FileSize;
use std::path::Path;

pub use walk_parallel::single_threaded::*;

/// Enum for messaging between workers/stealers
pub enum Status<T> {
    Done,
    Data(T),
}

/// The 'Walk' struct contains all the information we need to traverse a directory.
#[derive(Debug)]
pub struct Walk {
    pub path: PathBuf,
    gitignore: Option<RegexSet>,
    hgignore: Option<RegexSet>,
    darcs_boring: Option<RegexSet>,
    excludes: Option<Regex>,
    max_depth: Option<u8>,
    threshold: Option<u64>,
    start_depth: usize,
    nproc: usize,
    show_files: bool,
    get_blocks: bool,
    follow_symlinks: bool,
    artifacts_only: bool,
}

impl Walk {
    /// function to make output from a 'Walk', using one thread. It also takes an 'Arc<AtomicU64>'
    /// and will add the relevant directory sizes to it.
    pub fn print_dir(w: Walk, total: Arc<AtomicU64>) -> () {

        let excludes = match w.excludes {
            Some(ref x) => Some(x),
            _ => None,
        };

        let v = if excludes.is_some() || w.artifacts_only {
            read_all(
                &w.path,
                (w.start_depth as u8),
                w.max_depth,
                excludes,
                &w.gitignore,
                w.artifacts_only,
            )
        } else {
            read_all_fast(&w.path, (w.start_depth as u8), w.max_depth)
        };

        let subdir_size = v.file_size.get();

        total.fetch_add(subdir_size, Ordering::Relaxed);

        let mut to_print = if let Some(m) = w.threshold {
            subdir_size > m
        } else {
            true
        };

        if let Some(0) = w.max_depth {
            to_print = false;
        }

        if to_print {
            // filter by depth
            let mut v_filtered = v.filtered(w.threshold, !w.show_files, w.max_depth);

            v_filtered.display_tree(w.path);
        }
    }

    /// set the maximum depth to display
    pub fn set_depth(&mut self, d: u8) -> () {
        self.max_depth = Some(d);
    }

    /// set the regex for excludes
    pub fn set_regex(&mut self, r: Regex) -> () {
        self.excludes = Some(r);
    }

    /// set the minumum file size
    pub fn set_threshold(&mut self, n: u64) -> () {
        self.threshold = Some(n);
    }

    /// include files when printing
    pub fn with_files(&mut self) -> () {
        self.show_files = true;
    }

    /// include files when printing
    pub fn blocks(&mut self) -> () {
        self.get_blocks = true;
    }

    /// include files when printing
    pub fn artifacts_only(&mut self) -> () {
        self.artifacts_only = true;
    }

    fn get_proc(&self) -> usize {
        self.nproc
    }

    /// Create a new 'Walk' from a 'PathBuf' and the number
    /// of processor cores to be used.
    pub fn new(p: PathBuf, n: usize) -> Walk {
        Walk {
            path: p,
            gitignore: None,
            hgignore: None,
            darcs_boring: None,
            excludes: None,
            max_depth: None,
            threshold: None,
            start_depth: 0,
            nproc: n,
            show_files: false,
            get_blocks: false,
            follow_symlinks: false,
            artifacts_only: false,
        }
    }

    fn bump_depth(&mut self) -> () {
        self.start_depth += 1;
    }

    /// This takes a 'Walk' and a 'Worker<Status<Walk>>' and executes the walk *in parallel*,
    /// creating new work for each subdirectory. It's not the most efficient concurrency
    /// imaginable, but it's fast and easy-ish to use. It *also* takes in an 'Arc<AtomicU64>',
    /// which it updates with any file sizes in the directory.
    pub fn push_subdir(
        w: &Walk,
        worker: &mut chase_lev::Worker<Status<Walk>>,
        total: Arc<AtomicU64>,
    ) {

        let in_paths = &w.path;

        // fill up queue + print out files
        if let Ok(paths) = fs::read_dir(in_paths) {

            // iterate over all the entries in the directory
            for p in paths {
                let val = match p {
                    Ok(x) => x,
                    _ => {
                        eprintln!("{}: path error at {:?}.", "Error".red(), p);
                        exit(0x0001)
                    }
                };

                let exclude_check = if let Some(ref x) = w.excludes {
                    if let Some(r) = val.path().into_os_string().to_str() {
                        !x.is_match(r)
                    } else {
                        eprintln!(
                            "{}: ignoring invalid unicode at: {:?}",
                            "Warning".yellow(),
                            val.path().display()
                        );
                        true
                    }
                } else {
                    true
                };

                if exclude_check {
                    match val.file_type() {
                        Ok(t) => {
                            if t.is_dir() {
                                let mut new_path = w.path.to_owned();
                                new_path.push(val.file_name());
                                let mut new_walk = Walk::new(new_path, w.get_proc());
                                if w.excludes.is_some() {
                                    new_walk.set_regex(w.excludes.clone().unwrap());
                                }
                                if w.show_files {
                                    new_walk.with_files();
                                }
                                new_walk.bump_depth();
                                if let Some(d) = w.max_depth {
                                    new_walk.set_depth(d);
                                }
                                if let Some(b) = w.threshold {
                                    new_walk.set_threshold(b);
                                }
                                worker.push(Status::Data(new_walk)); // pass a vector of Arc's to do 2-level traversals?
                            } else if t.is_file() {
                                if let Ok(l) = val.metadata() {
                                    let size = size(&l, w.get_blocks); // l.len();
                                    total.fetch_add(size, Ordering::Relaxed);
                                    if w.show_files && size != 0 {
                                        let to_formatted = format!("{}", FileSize::new(size));
                                        println!(
                                            "{}\t {}",
                                            &to_formatted.green(),
                                            val.path().display()
                                        );
                                    }
                                } else {
                                    eprintln!(
                                        "{}: could not find filesize for file at {}.",
                                        "Warning".yellow(),
                                        val.path().display()
                                    );
                                }
                            }
                        }
                        _ => {
                            eprintln!(
                                "{}: could not determine file type for: {}",
                                "Warning".yellow(),
                                val.path().display()
                            )
                        }
                    }
                }
            }

            // send "done" messages to all the workers
            let iter = 0..(w.get_proc());
            iter.map(|_| worker.push(Status::Done)).count();

        }
        // if we can't read the directory contents, figure out why
        // 1: check the path exists
        else if !in_paths.exists() {
            eprintln!(
                "{}: path '{}' does not exist, or you do not have permission to enter.",
                "Error".red(),
                &in_paths.display()
            );
        }
        // 2: check the path is actually a directory
        else if !in_paths.is_dir() {
            if w.artifacts_only {
                eprintln!(
                    "{}: {} is not a directory; not searching for artifacts",
                    "Warning".yellow(),
                    &in_paths.display()
                );
            }

            if let Ok(l) = in_paths.metadata() {
                let size = size(&l, w.get_blocks); // l.len();
                let to_formatted = format!("{}", FileSize::new(size));
                println!("{}\t {}", &to_formatted.green(), in_paths.display());
            } else {
                panic!("{}", Internal::IoError);
            }
        }
        // 3: otherwise, give a warning about permissions
        else {
            eprintln!(
                "{}: permission denied for directory: {}",
                "Warning".yellow(),
                &in_paths.display()
            );
        }

    }
}

fn latex_log<P: AsRef<Path>>(p: P) -> bool {

    lazy_static! {
        static ref LOG: Regex =
            Regex::new(r"\.log$")
            .unwrap();
    }

    if LOG.is_match(&p.as_ref().to_string_lossy().to_string()) {
        let mut parent = (&p.as_ref())
            .parent()
            .unwrap()
            .to_string_lossy()
            .to_string();
        parent.push_str("/*.tex");
        glob_exists(&parent)
    } else {
        false
    }

}

// TODO figure out why the unwrap_or is failing?
// FIXME take optional reference to a regex
pub fn clean_project_dirs<P: AsRef<Path>>(p: P, exclude: Option<Regex>) -> () {

    lazy_static! {
        static ref REGEX: Regex =
            Regex::new(r"\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|hi|hc|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|pyc|mod|go\.(v|teak|xmldef)|p_hi|p_o|prof|hide-cache|tix|synctex\.gz)$")
            .unwrap();
    }

    for dir in WalkDir::new(p)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|p| {
            exclude.clone().map(|e| {
                e.is_match(&p.path().to_string_lossy().to_string())
            }) != Some(false)
        })
        .filter(|p| {
            REGEX.is_match(&p.path().to_string_lossy().to_string()) ||
                is_project_dir(
                    &p.path().to_string_lossy().to_string(),
                    &p.path()
                        .file_name()
                        .map(|x| x.to_string_lossy().to_string())
                        .unwrap_or("".to_string()),
                ) || latex_log(&p.path())
        })
    {
        if dir.file_type().is_file() {
            fs::remove_file(dir.path()).unwrap_or(());
        } else if dir.file_type().is_dir() {
            fs::remove_dir_all(dir.path()).unwrap_or(());
        }
    }
}

/// Given a 'Walk' struct, traverse it concurrently and print out any relevant outputs.
/// Currently, this only works for a depth of two, which is probably bad.
pub fn print_parallel(w: Walk) -> () {

    // initialize the total at 0 and create a reference to it
    let val = AtomicU64::new(0);
    let arc = Arc::new(val);
    let arc_producer = arc.clone();
    let arc_child = arc.clone();
    let path_display = w.path.clone();

    // set up worker & stealer
    let (mut worker, stealer): (chase_lev::Worker<Status<Walk>>,
                                chase_lev::Stealer<Status<Walk>>) = chase_lev::deque();

    // set up our iterator for the workers
    let iter = 0..(&w.get_proc() - 1);

    // create the producer in another thread
    let child_producer = thread::spawn(move || {

        let arc_local = arc_producer.clone();

        // assign work to everyone
        Walk::push_subdir(&w, &mut worker, arc_local.clone());

        // start popping off values in the worker's thread
        loop {
            if let Some(p) = worker.try_pop() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        }

    });

    // create a vector of thread handles so that it doesn't execute
    // everything sequentially.
    let mut threads = Vec::new();

    // set up as many workers as we have threads
    for _ in iter {

        // create a new stealer
        let stealer_clone = stealer.clone();

        let arc_local = arc_child.clone();

        // run the stealer in a new thread
        let child_consumer = thread::spawn(move || loop {

            if let chase_lev::Steal::Data(p) = stealer_clone.steal() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        });

        threads.push(child_consumer);

    }

    // join the child producer to the main thread
    let _ = child_producer.join();

    // join the workers to the main thread
    let _ = threads
        .into_iter()
        .map(|v| {
            let result = v.join();
            if let Ok(exit) = result {
                exit
            } else if let Err(e) = result {
                panic!("{:?}", e)
            }
        })
        .count();

    // get the total size
    let m = arc.load(Ordering::SeqCst); // TODO - check if this works with Relaxed?
    let size = FileSize::new(m);

    // print directory total.
    if size != FileSize::new(0) {
        let to_formatted = format!("{}", size);
        println!("{}\t {}", &to_formatted.green(), path_display.display());
    }

}
<commit_msg>clean hspec-failures<commit_after>extern crate crossbeam;
extern crate walkdir;

pub mod single_threaded;

use std::sync::Arc;
use std::sync::atomic::{AtomicU64, Ordering};
use std::fs;
use self::crossbeam::sync::chase_lev;
use self::walkdir::WalkDir;
use regex::{RegexSet, Regex};
use std::path::PathBuf;
use colored::*;
use std::process::exit;
use utils::size;
use std::thread;
use error::*;
use types::FileSize;
use std::path::Path;

pub use walk_parallel::single_threaded::*;

/// Enum for messaging between workers/stealers
pub enum Status<T> {
    Done,
    Data(T),
}

/// The 'Walk' struct contains all the information we need to traverse a directory.
#[derive(Debug)]
pub struct Walk {
    pub path: PathBuf,
    gitignore: Option<RegexSet>,
    hgignore: Option<RegexSet>,
    darcs_boring: Option<RegexSet>,
    excludes: Option<Regex>,
    max_depth: Option<u8>,
    threshold: Option<u64>,
    start_depth: usize,
    nproc: usize,
    show_files: bool,
    get_blocks: bool,
    follow_symlinks: bool,
    artifacts_only: bool,
}

impl Walk {
    /// function to make output from a 'Walk', using one thread. It also takes an 'Arc<AtomicU64>'
    /// and will add the relevant directory sizes to it.
    pub fn print_dir(w: Walk, total: Arc<AtomicU64>) -> () {

        let excludes = match w.excludes {
            Some(ref x) => Some(x),
            _ => None,
        };

        let v = if excludes.is_some() || w.artifacts_only {
            read_all(
                &w.path,
                (w.start_depth as u8),
                w.max_depth,
                excludes,
                &w.gitignore,
                w.artifacts_only,
            )
        } else {
            read_all_fast(&w.path, (w.start_depth as u8), w.max_depth)
        };

        let subdir_size = v.file_size.get();

        total.fetch_add(subdir_size, Ordering::Relaxed);

        let mut to_print = if let Some(m) = w.threshold {
            subdir_size > m
        } else {
            true
        };

        if let Some(0) = w.max_depth {
            to_print = false;
        }

        if to_print {
            // filter by depth
            let mut v_filtered = v.filtered(w.threshold, !w.show_files, w.max_depth);

            v_filtered.display_tree(w.path);
        }
    }

    /// set the maximum depth to display
    pub fn set_depth(&mut self, d: u8) -> () {
        self.max_depth = Some(d);
    }

    /// set the regex for excludes
    pub fn set_regex(&mut self, r: Regex) -> () {
        self.excludes = Some(r);
    }

    /// set the minumum file size
    pub fn set_threshold(&mut self, n: u64) -> () {
        self.threshold = Some(n);
    }

    /// include files when printing
    pub fn with_files(&mut self) -> () {
        self.show_files = true;
    }

    /// include files when printing
    pub fn blocks(&mut self) -> () {
        self.get_blocks = true;
    }

    /// include files when printing
    pub fn artifacts_only(&mut self) -> () {
        self.artifacts_only = true;
    }

    fn get_proc(&self) -> usize {
        self.nproc
    }

    /// Create a new 'Walk' from a 'PathBuf' and the number
    /// of processor cores to be used.
    pub fn new(p: PathBuf, n: usize) -> Walk {
        Walk {
            path: p,
            gitignore: None,
            hgignore: None,
            darcs_boring: None,
            excludes: None,
            max_depth: None,
            threshold: None,
            start_depth: 0,
            nproc: n,
            show_files: false,
            get_blocks: false,
            follow_symlinks: false,
            artifacts_only: false,
        }
    }

    fn bump_depth(&mut self) -> () {
        self.start_depth += 1;
    }

    /// This takes a 'Walk' and a 'Worker<Status<Walk>>' and executes the walk *in parallel*,
    /// creating new work for each subdirectory. It's not the most efficient concurrency
    /// imaginable, but it's fast and easy-ish to use. It *also* takes in an 'Arc<AtomicU64>',
    /// which it updates with any file sizes in the directory.
    pub fn push_subdir(
        w: &Walk,
        worker: &mut chase_lev::Worker<Status<Walk>>,
        total: Arc<AtomicU64>,
    ) {

        let in_paths = &w.path;

        // fill up queue + print out files
        if let Ok(paths) = fs::read_dir(in_paths) {

            // iterate over all the entries in the directory
            for p in paths {
                let val = match p {
                    Ok(x) => x,
                    _ => {
                        eprintln!("{}: path error at {:?}.", "Error".red(), p);
                        exit(0x0001)
                    }
                };

                let exclude_check = if let Some(ref x) = w.excludes {
                    if let Some(r) = val.path().into_os_string().to_str() {
                        !x.is_match(r)
                    } else {
                        eprintln!(
                            "{}: ignoring invalid unicode at: {:?}",
                            "Warning".yellow(),
                            val.path().display()
                        );
                        true
                    }
                } else {
                    true
                };

                if exclude_check {
                    match val.file_type() {
                        Ok(t) => {
                            if t.is_dir() {
                                let mut new_path = w.path.to_owned();
                                new_path.push(val.file_name());
                                let mut new_walk = Walk::new(new_path, w.get_proc());
                                if w.excludes.is_some() {
                                    new_walk.set_regex(w.excludes.clone().unwrap());
                                }
                                if w.show_files {
                                    new_walk.with_files();
                                }
                                new_walk.bump_depth();
                                if let Some(d) = w.max_depth {
                                    new_walk.set_depth(d);
                                }
                                if let Some(b) = w.threshold {
                                    new_walk.set_threshold(b);
                                }
                                worker.push(Status::Data(new_walk)); // pass a vector of Arc's to do 2-level traversals?
                            } else if t.is_file() {
                                if let Ok(l) = val.metadata() {
                                    let size = size(&l, w.get_blocks); // l.len();
                                    total.fetch_add(size, Ordering::Relaxed);
                                    if w.show_files && size != 0 {
                                        let to_formatted = format!("{}", FileSize::new(size));
                                        println!(
                                            "{}\t {}",
                                            &to_formatted.green(),
                                            val.path().display()
                                        );
                                    }
                                } else {
                                    eprintln!(
                                        "{}: could not find filesize for file at {}.",
                                        "Warning".yellow(),
                                        val.path().display()
                                    );
                                }
                            }
                        }
                        _ => {
                            eprintln!(
                                "{}: could not determine file type for: {}",
                                "Warning".yellow(),
                                val.path().display()
                            )
                        }
                    }
                }
            }

            // send "done" messages to all the workers
            let iter = 0..(w.get_proc());
            iter.map(|_| worker.push(Status::Done)).count();

        }
        // if we can't read the directory contents, figure out why
        // 1: check the path exists
        else if !in_paths.exists() {
            eprintln!(
                "{}: path '{}' does not exist, or you do not have permission to enter.",
                "Error".red(),
                &in_paths.display()
            );
        }
        // 2: check the path is actually a directory
        else if !in_paths.is_dir() {
            if w.artifacts_only {
                eprintln!(
                    "{}: {} is not a directory; not searching for artifacts",
                    "Warning".yellow(),
                    &in_paths.display()
                );
            }

            if let Ok(l) = in_paths.metadata() {
                let size = size(&l, w.get_blocks); // l.len();
                let to_formatted = format!("{}", FileSize::new(size));
                println!("{}\t {}", &to_formatted.green(), in_paths.display());
            } else {
                panic!("{}", Internal::IoError);
            }
        }
        // 3: otherwise, give a warning about permissions
        else {
            eprintln!(
                "{}: permission denied for directory: {}",
                "Warning".yellow(),
                &in_paths.display()
            );
        }

    }
}

fn latex_log<P: AsRef<Path>>(p: P) -> bool {

    lazy_static! {
        static ref LOG: Regex =
            Regex::new(r"\.log$")
            .unwrap();
    }

    if LOG.is_match(&p.as_ref().to_string_lossy().to_string()) {
        let mut parent = (&p.as_ref())
            .parent()
            .unwrap()
            .to_string_lossy()
            .to_string();
        parent.push_str("/*.tex");
        glob_exists(&parent)
    } else {
        false
    }

}

// TODO figure out why the unwrap_or is failing?
// FIXME take optional reference to a regex
pub fn clean_project_dirs<P: AsRef<Path>>(p: P, exclude: Option<Regex>) -> () {

    lazy_static! {
        static ref REGEX: Regex =
            Regex::new(r"\.(a|la|lo|o|ll|keter|bc|dyn_o|d|rlib|crate|hi|hc|dyn_hi|S|jsexe|webapp|js\.externs|ibc|toc|aux|fdb_latexmk|fls|egg-info|whl|js_a|js_hi|jld|ji|js_o|so.*|dump-.*|vmb|crx|orig|elmo|elmi|hspec-failures|pyc|mod|go\.(v|teak|xmldef)|p_hi|p_o|prof|hide-cache|tix|synctex\.gz)$")
            .unwrap();
    }

    for dir in WalkDir::new(p)
        .into_iter()
        .filter_map(|e| e.ok())
        .filter(|p| {
            exclude.clone().map(|e| {
                e.is_match(&p.path().to_string_lossy().to_string())
            }) != Some(false)
        })
        .filter(|p| {
            REGEX.is_match(&p.path().to_string_lossy().to_string()) ||
                is_project_dir(
                    &p.path().to_string_lossy().to_string(),
                    &p.path()
                        .file_name()
                        .map(|x| x.to_string_lossy().to_string())
                        .unwrap_or("".to_string()),
                ) || latex_log(&p.path())
        })
    {
        if dir.file_type().is_file() {
            fs::remove_file(dir.path()).unwrap_or(());
        } else if dir.file_type().is_dir() {
            fs::remove_dir_all(dir.path()).unwrap_or(());
        }
    }
}

/// Given a 'Walk' struct, traverse it concurrently and print out any relevant outputs.
/// Currently, this only works for a depth of two, which is probably bad.
pub fn print_parallel(w: Walk) -> () {

    // initialize the total at 0 and create a reference to it
    let val = AtomicU64::new(0);
    let arc = Arc::new(val);
    let arc_producer = arc.clone();
    let arc_child = arc.clone();
    let path_display = w.path.clone();

    // set up worker & stealer
    let (mut worker, stealer): (chase_lev::Worker<Status<Walk>>,
                                chase_lev::Stealer<Status<Walk>>) = chase_lev::deque();

    // set up our iterator for the workers
    let iter = 0..(&w.get_proc() - 1);

    // create the producer in another thread
    let child_producer = thread::spawn(move || {

        let arc_local = arc_producer.clone();

        // assign work to everyone
        Walk::push_subdir(&w, &mut worker, arc_local.clone());

        // start popping off values in the worker's thread
        loop {
            if let Some(p) = worker.try_pop() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        }

    });

    // create a vector of thread handles so that it doesn't execute
    // everything sequentially.
    let mut threads = Vec::new();

    // set up as many workers as we have threads
    for _ in iter {

        // create a new stealer
        let stealer_clone = stealer.clone();

        let arc_local = arc_child.clone();

        // run the stealer in a new thread
        let child_consumer = thread::spawn(move || loop {

            if let chase_lev::Steal::Data(p) = stealer_clone.steal() {
                match p {
                    Status::Data(d) => Walk::print_dir(d, arc_local.clone()),
                    _ => break,
                };
            }
        });

        threads.push(child_consumer);

    }

    // join the child producer to the main thread
    let _ = child_producer.join();

    // join the workers to the main thread
    let _ = threads
        .into_iter()
        .map(|v| {
            let result = v.join();
            if let Ok(exit) = result {
                exit
            } else if let Err(e) = result {
                panic!("{:?}", e)
            }
        })
        .count();

    // get the total size
    let m = arc.load(Ordering::SeqCst); // TODO - check if this works with Relaxed?
    let size = FileSize::new(m);

    // print directory total.
    if size != FileSize::new(0) {
        let to_formatted = format!("{}", size);
        println!("{}\t {}", &to_formatted.green(), path_display.display());
    }

}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax::{ast, attr};
use llvm::LLVMRustHasFeature;
use rustc::session::Session;
use rustc_trans::back::write::create_target_machine;
use syntax::parse::token::InternedString;
use syntax::parse::token::intern_and_get_ident as intern;
use libc::c_char;

// WARNING: the features must be known to LLVM or the feature
// detection code will walk past the end of the feature array,
// leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &[
    "neon\0",
    "vfp2\0",
    "vfp3\0",
    "vfp4\0",
];

const X86_WHITELIST: &'static [&'static str] = &[
    "avx\0",
    "avx2\0",
    "sse\0",
    "sse2\0",
    "sse3\0",
    "sse4.1\0",
    "sse4.2\0",
    "ssse3\0",
];

/// Add `target_feature = "..."` cfgs for a variety of platform
/// specific features (SSE, NEON etc.).
///
/// This is performed by checking whether a whitelisted set of
/// features is available on the target machine, by querying LLVM.
pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
    let target_machine = create_target_machine(sess);

    let whitelist = match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        _ => &[],
    };

    let tf = InternedString::new("target_feature");
    for feat in whitelist {
        if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
            cfg.push(attr::mk_name_value_item_str(tf.clone(), intern(&feat[..feat.len()-1])))
        }
    }
}
<commit_msg>Check that the feature strings are well-formed<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax::{ast, attr};
use llvm::LLVMRustHasFeature;
use rustc::session::Session;
use rustc_trans::back::write::create_target_machine;
use syntax::parse::token::InternedString;
use syntax::parse::token::intern_and_get_ident as intern;
use libc::c_char;

// WARNING: the features must be known to LLVM or the feature
// detection code will walk past the end of the feature array,
// leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &[
    "neon\0",
    "vfp2\0",
    "vfp3\0",
    "vfp4\0",
];

const X86_WHITELIST: &'static [&'static str] = &[
    "avx\0",
    "avx2\0",
    "sse\0",
    "sse2\0",
    "sse3\0",
    "sse4.1\0",
    "sse4.2\0",
    "ssse3\0",
];

/// Add `target_feature = "..."` cfgs for a variety of platform
/// specific features (SSE, NEON etc.).
///
/// This is performed by checking whether a whitelisted set of
/// features is available on the target machine, by querying LLVM.
pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) {
    let target_machine = create_target_machine(sess);

    let whitelist = match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        _ => &[],
    };

    let tf = InternedString::new("target_feature");
    for feat in whitelist {
        assert_eq!(feat.chars().last(), Some('\0'));
        if unsafe { LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
            cfg.push(attr::mk_name_value_item_str(tf.clone(), intern(&feat[..feat.len()-1])))
        }
    }
}
<|endoftext|>