<commit_before>/// Utilities for writing messages to the Janus log.
extern crate chrono;
extern crate colored;

use self::chrono::{DateTime, Local};
use self::colored::{Color, Colorize};
use super::ffi;
use std::ffi::CString;
use std::fmt::Write;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
/// A Janus log level. Lower is more severe.
pub enum LogLevel {
    Fatal = 1,
    Err = 2,
    Warn = 3,
    Info = 4,
    Verb = 5,
    Huge = 6,
    Dbg = 7,
}

impl LogLevel {
    /// The color associated with each log level's label (if colors are enabled.)
    fn color(&self) -> Option<Color> {
        match *self {
            LogLevel::Fatal => Some(Color::Magenta),
            LogLevel::Err => Some(Color::Red),
            LogLevel::Warn => Some(Color::Yellow),
            _ => None,
        }
    }
}

#[derive(Debug, Clone)]
pub struct LogParameters {
    pub max_log_level: i32,
    pub log_timestamps: bool,
    pub log_colors: bool,
    pub clock: fn() -> DateTime<Local>,
}

impl Default for LogParameters {
    fn default() -> Self {
        unsafe {
            Self {
                max_log_level: ffi::janus_log_level,
                log_timestamps: ffi::janus_log_timestamps == 1,
                log_colors: ffi::janus_log_colors == 1,
                clock: Local::now,
            }
        }
    }
}

/// Writes a message at the given log level to the Janus log, using the provided parameters to control
/// how the log message is formatted.
pub fn write_log(level: LogLevel, message: &str, params: LogParameters) {
    if level as i32 <= params.max_log_level {
        let output = CString::new(print_log(level, message, params)).expect("Null character in log message :(");
        unsafe { ffi::janus_vprintf(output.as_ptr()) }
    }
}

/// Prints a message at the given log level into an owned string, using the provided parameters to control
/// how the log message is formatted.
pub fn print_log(level: LogLevel, message: &str, params: LogParameters) -> String {
    let mut output = String::with_capacity(message.len() + 40);
    if params.log_timestamps {
        write!(output, "{} ", (params.clock)().format("[%a %b %e %T %Y]")).unwrap();
    }
    if level <= LogLevel::Warn {
        let name = format!("[{:?}] ", level).to_uppercase();
        match level.color() {
            Some(c) if params.log_colors => output.push_str(&name.color(c)),
            _ => output.push_str(&name),
        }
    }
    output.push_str(message);
    output.push('\n');
    output
}

/// Writes a message at the given log level to the Janus log.
pub fn log(level: LogLevel, message: &str) {
    write_log(level, message, LogParameters::default());
}

#[cfg(test)]
mod tests {

    use super::*;
    use super::chrono::TimeZone;

    fn fixed_clock(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32) -> DateTime<Local> {
        Local.ymd(year, month, day).and_hms(hour, min, sec)
    }

    #[test]
    fn log_format_correctness() {
        assert_eq!(
            "[Tue Oct 10 01:37:46 2017] [WARN] Test message.\n",
            print_log(
                LogLevel::Warn,
                "Test message.",
                LogParameters {
                    max_log_level: 6,
                    log_timestamps: true,
                    log_colors: false,
                    clock: || fixed_clock(2017, 10, 10, 1, 37, 46),
                }
            )
        )
    }
}
<commit_msg>Fix colored log output<commit_after>/// Utilities for writing messages to the Janus log.
extern crate chrono;
extern crate colored;

use self::chrono::{DateTime, Local};
use self::colored::{Color, Colorize};
use super::ffi;
use std::ffi::CString;
use std::fmt::Write;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
/// A Janus log level. Lower is more severe.
pub enum LogLevel {
    Fatal = 1,
    Err = 2,
    Warn = 3,
    Info = 4,
    Verb = 5,
    Huge = 6,
    Dbg = 7,
}

impl LogLevel {
    /// The color associated with each log level's label (if colors are enabled.)
    fn color(&self) -> Option<Color> {
        match *self {
            LogLevel::Fatal => Some(Color::Magenta),
            LogLevel::Err => Some(Color::Red),
            LogLevel::Warn => Some(Color::Yellow),
            _ => None,
        }
    }
}

#[derive(Debug, Clone)]
pub struct LogParameters {
    pub max_log_level: i32,
    pub log_timestamps: bool,
    pub log_colors: bool,
    pub clock: fn() -> DateTime<Local>,
}

impl Default for LogParameters {
    fn default() -> Self {
        unsafe {
            Self {
                max_log_level: ffi::janus_log_level,
                log_timestamps: ffi::janus_log_timestamps == 1,
                log_colors: ffi::janus_log_colors == 1,
                clock: Local::now,
            }
        }
    }
}

/// Writes a message at the given log level to the Janus log, using the provided parameters to control
/// how the log message is formatted.
pub fn write_log(level: LogLevel, message: &str, params: LogParameters) {
    if level as i32 <= params.max_log_level {
        let output = CString::new(print_log(level, message, params)).expect("Null character in log message :(");
        unsafe { ffi::janus_vprintf(output.as_ptr()) }
    }
}

/// Prints a message at the given log level into an owned string, using the provided parameters to control
/// how the log message is formatted.
pub fn print_log(level: LogLevel, message: &str, params: LogParameters) -> String {
    let mut output = String::with_capacity(message.len() + 40);
    if params.log_timestamps {
        write!(output, "{} ", (params.clock)().format("[%a %b %e %T %Y]")).unwrap();
    }
    if level <= LogLevel::Warn {
        let name = format!("[{:?}] ", level).to_uppercase();
        match level.color() {
            Some(c) if params.log_colors => write!(output, "{}", name.color(c)).unwrap(),
            _ => output.push_str(&name),
        }
    }
    output.push_str(message);
    output.push('\n');
    output
}

/// Writes a message at the given log level to the Janus log.
pub fn log(level: LogLevel, message: &str) {
    write_log(level, message, LogParameters::default());
}

#[cfg(test)]
mod tests {

    use super::*;
    use super::chrono::TimeZone;

    fn fixed_clock(year: i32, month: u32, day: u32, hour: u32, min: u32, sec: u32) -> DateTime<Local> {
        Local.ymd(year, month, day).and_hms(hour, min, sec)
    }

    #[test]
    fn log_format_correctness() {
        assert_eq!(
            "[Tue Oct 10 01:37:46 2017] [WARN] Test message.\n",
            print_log(
                LogLevel::Warn,
                "Test message.",
                LogParameters {
                    max_log_level: 6,
                    log_timestamps: true,
                    log_colors: false,
                    clock: || fixed_clock(2017, 10, 10, 1, 37, 46),
                }
            )
        )
    }
}
<|endoftext|>


<commit_before>//! Commands from the user to manipulate the tree

use super::try_lock_tree;
use super::{ContainerType, Direction, Handle, Layout, TreeError};
use super::Tree;

use uuid::Uuid;
use rustwlc::{Geometry, Point, ResizeEdge, WlcView, WlcOutput, ViewType};

pub type CommandResult = Result<(), TreeError>;

pub fn remove_active() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.remove_active();
    }
}

pub fn tile_switch() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_horizontal();
        tree.layout_active_of(ContainerType::Workspace)
            .unwrap_or_else(|_| {
                error!("Could not tile workspace");
            });
    }
}

pub fn split_vertical() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Vertical);
    }
}

pub fn split_horizontal() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Horizontal);
    }
}

pub fn focus_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Left)
            .unwrap_or_else(|_| {
                error!("Could not focus left");
            });
    }
}

pub fn focus_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Right)
            .unwrap_or_else(|_| {
                error!("Could not focus right");
            });
    }
}

pub fn focus_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Up)
            .unwrap_or_else(|_| {
                error!("Could not focus up");
            });
    }
}

pub fn focus_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Down)
            .unwrap_or_else(|_| {
                error!("Could not focus down");
            });
    }
}

/* Commands that can be chained together with a locked tree */

impl Tree {

    /// Adds an Output to the tree. Never fails
    pub fn add_output(&mut self, output: WlcOutput) -> CommandResult {
        self.0.add_output(output);
        Ok(())
    }

    /// Adds a Workspace to the tree. Never fails
    pub fn switch_to_workspace(&mut self, name: &str) -> CommandResult {
        self.0.switch_to_workspace(name);
        Ok(())
    }

    /// Tiles the active container of some container type. Never fails
    pub fn layout_active_of(&mut self, c_type: ContainerType) -> CommandResult {
        self.0.layout_active_of(c_type);
        Ok(())
    }

    /// Adds a view to the workspace of the active container
    pub fn add_view(&mut self, view: WlcView) -> CommandResult {
        let tree = &mut self.0;
        let output = view.get_output();
        if tree.get_active_container().is_none() {
            return Err(TreeError::NoActiveContainer)
        }
        view.set_mask(output.get_mask());
        let v_type = view.get_type();
        let v_class = view.get_class();
        // If it is empty, don't add to tree
        if v_type != ViewType::empty() {
            // Now focused on something outside the tree,
            // have to unset the active container
            if !tree.active_is_root() {
                tree.unset_active_container();
            }
            return Ok(())
        }
        if v_class.as_str() == "Background" {
            info!("Setting background: {}", view.get_title());
            view.send_to_back();
            let output = view.get_output();
            let resolution = output.get_resolution().clone();
            let fullscreen = Geometry {
                origin: Point { x: 0, y: 0 },
                size: resolution
            };
            view.set_geometry(ResizeEdge::empty(), &fullscreen);
            return Ok(());
        }
        tree.add_view(view.clone());
        tree.normalize_view(view.clone());
        tree.layout_active_of(ContainerType::Container);
        Ok(())
    }

    /// Attempts to remove a view from the tree. If it is not in the tree it fails
    pub fn remove_view(&mut self, view: WlcView) -> CommandResult {
        self.0.remove_view(&view)
    }

    #[allow(dead_code)]
    /// Attempts to remove a container based on UUID. Fails if the container
    /// cannot be removed or if the container does not exist.
    pub fn remove_view_by_id(&mut self, id: Uuid) -> CommandResult {
        if let Some(node_ix) = self.0.tree.lookup_id(id) {
            match self.0.tree[node_ix].get_type() {
                ContainerType::View => {
                    let handle = match self.0.tree[node_ix].get_handle()
                        .expect("Could not get handle") {
                            Handle::View(ref handle) => handle.clone(),
                            _ => unreachable!()
                        };
                    return self.remove_view(handle)
                },
                _ => {
                    Err(TreeError::UuidNotAssociatedWith(ContainerType::View))
                }
            }
        } else {
            Err(TreeError::NodeNotFound(id))
        }
    }

    /// Sets the view to be the new active container. Never fails
    pub fn set_active_view(&mut self, view: WlcView) -> CommandResult {
        self.0.set_active_container(view.clone());
        view.focus();
        Ok(())
    }

    #[allow(dead_code)]
    /// Sets the active container to be the container at the UUID
    /// Fails if the container is not a container or view, or if the
    /// container does not exist
    pub fn set_active_container_by_id(&mut self, id: Uuid) -> CommandResult {
        if let Some(node_ix) = self.0.tree.lookup_id(id) {
            match self.0.tree[node_ix].get_type() {
                ContainerType::View | ContainerType::Container => {
                    self.0.active_container = Some(node_ix);
                    Ok(())
                },
                _ => {
                    Err(TreeError::UuuidWrongType(self.0.tree[node_ix].clone(),
                                                  vec!(ContainerType::View,
                                                       ContainerType::Container)))
                }

            }
        } else {
            Err(TreeError::NodeNotFound(id))
        }
    }

    /// Destroy the tree
    pub fn destroy_tree(&mut self) -> CommandResult {
        self.0.destroy_tree();
        Ok(())
    }

    pub fn move_focus(&mut self, dir: Direction) -> CommandResult {
        self.0.move_focus(dir);
        Ok(())
    }

    /// Moves the active container to a workspace
    pub fn send_active_to_workspace(&mut self, workspace_name: &str) -> CommandResult {
        self.0.send_active_to_workspace(workspace_name);
        Ok(())
    }
}
<commit_msg>Fixed windows not resizing when active removed<commit_after>//! Commands from the user to manipulate the tree

use super::try_lock_tree;
use super::{ContainerType, Direction, Handle, Layout, TreeError};
use super::Tree;

use uuid::Uuid;
use rustwlc::{Geometry, Point, ResizeEdge, WlcView, WlcOutput, ViewType};

pub type CommandResult = Result<(), TreeError>;

pub fn remove_active() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.remove_active();
        tree.0.layout_active_of(ContainerType::Root);
    }
}

pub fn tile_switch() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_horizontal();
        tree.layout_active_of(ContainerType::Workspace)
            .unwrap_or_else(|_| {
                error!("Could not tile workspace");
            });
    }
}

pub fn split_vertical() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Vertical);
    }
}

pub fn split_horizontal() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.0.toggle_active_layout(Layout::Horizontal);
    }
}

pub fn focus_left() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Left)
            .unwrap_or_else(|_| {
                error!("Could not focus left");
            });
    }
}

pub fn focus_right() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Right)
            .unwrap_or_else(|_| {
                error!("Could not focus right");
            });
    }
}

pub fn focus_up() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Up)
            .unwrap_or_else(|_| {
                error!("Could not focus up");
            });
    }
}

pub fn focus_down() {
    if let Ok(mut tree) = try_lock_tree() {
        tree.move_focus(Direction::Down)
            .unwrap_or_else(|_| {
                error!("Could not focus down");
            });
    }
}

/* Commands that can be chained together with a locked tree */

impl Tree {

    /// Adds an Output to the tree. Never fails
    pub fn add_output(&mut self, output: WlcOutput) -> CommandResult {
        self.0.add_output(output);
        Ok(())
    }

    /// Adds a Workspace to the tree. Never fails
    pub fn switch_to_workspace(&mut self, name: &str) -> CommandResult {
        self.0.switch_to_workspace(name);
        Ok(())
    }

    /// Tiles the active container of some container type. Never fails
    pub fn layout_active_of(&mut self, c_type: ContainerType) -> CommandResult {
        self.0.layout_active_of(c_type);
        Ok(())
    }

    /// Adds a view to the workspace of the active container
    pub fn add_view(&mut self, view: WlcView) -> CommandResult {
        let tree = &mut self.0;
        let output = view.get_output();
        if tree.get_active_container().is_none() {
            return Err(TreeError::NoActiveContainer)
        }
        view.set_mask(output.get_mask());
        let v_type = view.get_type();
        let v_class = view.get_class();
        // If it is empty, don't add to tree
        if v_type != ViewType::empty() {
            // Now focused on something outside the tree,
            // have to unset the active container
            if !tree.active_is_root() {
                tree.unset_active_container();
            }
            return Ok(())
        }
        if v_class.as_str() == "Background" {
            info!("Setting background: {}", view.get_title());
            view.send_to_back();
            let output = view.get_output();
            let resolution = output.get_resolution().clone();
            let fullscreen = Geometry {
                origin: Point { x: 0, y: 0 },
                size: resolution
            };
            view.set_geometry(ResizeEdge::empty(), &fullscreen);
            return Ok(());
        }
        tree.add_view(view.clone());
        tree.normalize_view(view.clone());
        tree.layout_active_of(ContainerType::Container);
        Ok(())
    }

    /// Attempts to remove a view from the tree. If it is not in the tree it fails
    pub fn remove_view(&mut self, view: WlcView) -> CommandResult {
        self.0.remove_view(&view)
    }

    #[allow(dead_code)]
    /// Attempts to remove a container based on UUID. Fails if the container
    /// cannot be removed or if the container does not exist.
    pub fn remove_view_by_id(&mut self, id: Uuid) -> CommandResult {
        if let Some(node_ix) = self.0.tree.lookup_id(id) {
            match self.0.tree[node_ix].get_type() {
                ContainerType::View => {
                    let handle = match self.0.tree[node_ix].get_handle()
                        .expect("Could not get handle") {
                            Handle::View(ref handle) => handle.clone(),
                            _ => unreachable!()
                        };
                    return self.remove_view(handle)
                },
                _ => {
                    Err(TreeError::UuidNotAssociatedWith(ContainerType::View))
                }
            }
        } else {
            Err(TreeError::NodeNotFound(id))
        }
    }

    /// Sets the view to be the new active container. Never fails
    pub fn set_active_view(&mut self, view: WlcView) -> CommandResult {
        self.0.set_active_container(view.clone());
        view.focus();
        Ok(())
    }

    #[allow(dead_code)]
    /// Sets the active container to be the container at the UUID
    /// Fails if the container is not a container or view, or if the
    /// container does not exist
    pub fn set_active_container_by_id(&mut self, id: Uuid) -> CommandResult {
        if let Some(node_ix) = self.0.tree.lookup_id(id) {
            match self.0.tree[node_ix].get_type() {
                ContainerType::View | ContainerType::Container => {
                    self.0.active_container = Some(node_ix);
                    Ok(())
                },
                _ => {
                    Err(TreeError::UuuidWrongType(self.0.tree[node_ix].clone(),
                                                  vec!(ContainerType::View,
                                                       ContainerType::Container)))
                }

            }
        } else {
            Err(TreeError::NodeNotFound(id))
        }
    }

    /// Destroy the tree
    pub fn destroy_tree(&mut self) -> CommandResult {
        self.0.destroy_tree();
        Ok(())
    }

    pub fn move_focus(&mut self, dir: Direction) -> CommandResult {
        self.0.move_focus(dir);
        Ok(())
    }

    /// Moves the active container to a workspace
    pub fn send_active_to_workspace(&mut self, workspace_name: &str) -> CommandResult {
        self.0.send_active_to_workspace(workspace_name);
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! A control flow graph represented as mappings of extended basic blocks to their predecessors.
//! Predecessors are denoted by tuples of EBB and branch/jump instructions. Each predecessor
//! tuple corresponds to the end of a basic block.
//!
//! ```c
//!     Ebb0:
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         brz vx, Ebb1 ; end of basic block
//!
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         jmp Ebb2     ; end of basic block
//! ```
//!
//! Here Ebb1 and Ebb2 would each have a single predecessor denoted as (Ebb0, `brz vx, Ebb1`)
//! and (Ebb0, `jmp Ebb2`) respectively.

use repr::Function;
use entities::{Inst, Ebb};
use instructions::InstructionData;
use std::collections::{BTreeSet, BTreeMap, btree_map};

/// A basic block denoted by its enclosing Ebb and last instruction.
pub type Predecessor = (Ebb, Inst);

/// Storing predecessors in a BTreeSet ensures that their ordering is
/// stable with no duplicates.
pub type PredecessorSet = BTreeSet<Predecessor>;

/// The Control Flow Graph maintains a mapping of ebbs to their predecessors
/// where predecessors are basic blocks.
#[derive(Debug)]
pub struct ControlFlowGraph {
    data: BTreeMap<Ebb, PredecessorSet>,
}

impl ControlFlowGraph {
    /// During initialization mappings will be generated for any existing
    /// blocks within the CFG's associated function. Basic sanity checks will
    /// also be performed to ensure that the blocks are well formed.
    pub fn new(func: &Function) -> Result<ControlFlowGraph, String> {
        let mut cfg = ControlFlowGraph { data: BTreeMap::new() };

        // Even ebbs without predecessors should show up in the CFG, albeit
        // with no entires.
        for ebb in func.ebbs_numerically() {
            try!(cfg.init_ebb(ebb));
        }

        for ebb in func.ebbs_numerically() {
            // Flips to true when a terminating instruction is seen. So that if additional
            // instructions occur an error may be returned.
            let mut terminated = false;
            for inst in func.ebb_insts(ebb) {
                if terminated {
                    return Err(format!("{} contains unreachable instructions.", ebb));
                }

                match func[inst] {
                    InstructionData::Branch { ty: _, opcode: _, ref data } => {
                        try!(cfg.add_predecessor(data.destination, (ebb, inst)));
                    }
                    InstructionData::Jump { ty: _, opcode: _, ref data } => {
                        try!(cfg.add_predecessor(data.destination, (ebb, inst)));
                        terminated = true;
                    }
                    InstructionData::Return { ty: _, opcode: _, data: _ } => {
                        terminated = true;
                    }
                    InstructionData::Nullary { ty: _, opcode: _ } => {
                        terminated = true;
                    }
                    _ => (),
                }
            }
        }
        Ok(cfg)
    }

    /// Initializes a predecessor set for some ebb. If an ebb already has an
    /// entry it will be clobbered.
    pub fn init_ebb(&mut self, ebb: Ebb) -> Result<&mut PredecessorSet, &'static str> {
        self.data.insert(ebb, BTreeSet::new());
        match self.data.get_mut(&ebb) {
            Some(predecessors) => Ok(predecessors),
            None => Err("Ebb initialization failed."),
        }
    }

    /// Attempts to add a predecessor for some ebb, attempting to initialize
    /// any ebb which has no entry.
    pub fn add_predecessor(&mut self,
                           ebb: Ebb,
                           predecessor: Predecessor)
                           -> Result<(), &'static str> {
        let success = match self.data.get_mut(&ebb) {
            Some(predecessors) => predecessors.insert(predecessor),
            None => false,
        };

        if success {
            Ok(())
        } else {
            let mut predecessors = try!(self.init_ebb(ebb));
            if predecessors.insert(predecessor) {
                return Ok(());
            }
            Err("Predecessor insertion failed.")
        }

    }

    /// Returns all of the predecessors for some ebb, if it has an entry.
    pub fn get_predecessors(&self, ebb: Ebb) -> Option<&PredecessorSet> {
        self.data.get(&ebb)
    }

    /// An iterator over all of the ebb to predecessor mappings in the CFG.
    pub fn iter<'a>(&'a self) -> btree_map::Iter<'a, Ebb, PredecessorSet> {
        self.data.iter()
    }
}

#[cfg(test)]
mod tests {
    use instructions::*;
    use entities::{Ebb, Inst, NO_VALUE};
    use repr::Function;
    use super::*;
    use types;

    // Some instructions will be re-used in several tests.

    fn nullary(func: &mut Function) -> Inst {
        func.make_inst(InstructionData::Nullary {
            opcode: Opcode::Iconst,
            ty: types::I32,
        })
    }

    fn jump(func: &mut Function, dest: Ebb) -> Inst {
        func.make_inst(InstructionData::Jump {
            opcode: Opcode::Jump,
            ty: types::VOID,
            data: Box::new(JumpData {
                destination: dest,
                arguments: VariableArgs::new(),
            }),
        })
    }

    fn branch(func: &mut Function, dest: Ebb) -> Inst {
        func.make_inst(InstructionData::Branch {
            opcode: Opcode::Brz,
            ty: types::VOID,
            data: Box::new(BranchData {
                arg: NO_VALUE,
                destination: dest,
                arguments: VariableArgs::new(),
            }),
        })
    }

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func).unwrap();
        assert_eq!(None, cfg.iter().next());
    }

    #[test]
    fn no_predecessors() {
        let mut func = Function::new();
        func.make_ebb();
        func.make_ebb();
        func.make_ebb();
        let cfg = ControlFlowGraph::new(&func).unwrap();
        let nodes = cfg.iter().collect::<Vec<_>>();
        assert_eq!(nodes.len(), 3);

        let mut fun_ebbs = func.ebbs_numerically();
        for (ebb, predecessors) in nodes {
            assert_eq!(ebb.index(), fun_ebbs.next().unwrap().index());
            assert_eq!(predecessors.len(), 0);
        }
    }

    #[test]
    #[should_panic(expected = "instructions")]
    fn nullable_before_branch() {
        // Ensure that branching after a nullary, within an ebb, triggers an error.
        let mut func = Function::new();
        let ebb0 = func.make_ebb();
        let ebb1_malformed = func.make_ebb();
        let ebb2 = func.make_ebb();

        let nullary_inst = nullary(&mut func);
        func.append_inst(ebb1_malformed, nullary_inst);

        // This jump should not be recorded since a nullary takes place
        // before it appears.
        let jmp_ebb1_ebb0 = jump(&mut func, ebb0);
        func.append_inst(ebb1_malformed, jmp_ebb1_ebb0);

        let jmp_ebb0_ebb2 = jump(&mut func, ebb2);
        func.append_inst(ebb0, jmp_ebb0_ebb2);

        ControlFlowGraph::new(&func).unwrap();
    }

    #[test]
    #[should_panic(expected = "instructions")]
    fn jump_before_branch() {
        // Ensure that branching after a jump, within an ebb, triggers an error.
        let mut func = Function::new();
        let ebb0 = func.make_ebb();
        let ebb1_malformed = func.make_ebb();
        let ebb2 = func.make_ebb();

        let jmp_ebb0_ebb1 = jump(&mut func, ebb2);
        func.append_inst(ebb0, jmp_ebb0_ebb1);

        let jmp_ebb1_ebb2 = jump(&mut func, ebb2);
        func.append_inst(ebb1_malformed, jmp_ebb1_ebb2);

        // This branch should not be recorded since a jump takes place
        // before it appears.
        let br_ebb1_ebb0 = branch(&mut func, ebb0);
        func.append_inst(ebb1_malformed, br_ebb1_ebb0);

        ControlFlowGraph::new(&func).unwrap();
    }

    #[test]
    fn branches_and_jumps() {
        let mut func = Function::new();
        let ebb0 = func.make_ebb();
        let ebb1 = func.make_ebb();
        let ebb2 = func.make_ebb();

        let br_ebb0_ebb2 = branch(&mut func, ebb2);
        func.append_inst(ebb0, br_ebb0_ebb2);

        let jmp_ebb0_ebb1 = jump(&mut func, ebb1);
        func.append_inst(ebb0, jmp_ebb0_ebb1);

        let br_ebb1_ebb1 = branch(&mut func, ebb1);
        func.append_inst(ebb1, br_ebb1_ebb1);

        let jmp_ebb1_ebb2 = jump(&mut func, ebb2);
        func.append_inst(ebb1, jmp_ebb1_ebb2);

        let cfg = ControlFlowGraph::new(&func).unwrap();
        let ebb0_predecessors = cfg.get_predecessors(ebb0).unwrap();
        let ebb1_predecessors = cfg.get_predecessors(ebb1).unwrap();
        let ebb2_predecessors = cfg.get_predecessors(ebb2).unwrap();
        assert_eq!(ebb0_predecessors.len(), 0);
        assert_eq!(ebb1_predecessors.len(), 2);
        assert_eq!(ebb2_predecessors.len(), 2);

        assert_eq!(ebb1_predecessors.contains(&(ebb0, jmp_ebb0_ebb1)), true);
        assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), true);
    }

}
<commit_msg>Remove misleading test comments<commit_after>//! A control flow graph represented as mappings of extended basic blocks to their predecessors.
//! Predecessors are denoted by tuples of EBB and branch/jump instructions. Each predecessor
//! tuple corresponds to the end of a basic block.
//!
//! ```c
//!     Ebb0:
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         brz vx, Ebb1 ; end of basic block
//!
//!         ...          ; beginning of basic block
//!
//!         ...
//!
//!         jmp Ebb2     ; end of basic block
//! ```
//!
//! Here Ebb1 and Ebb2 would each have a single predecessor denoted as (Ebb0, `brz vx, Ebb1`)
//! and (Ebb0, `jmp Ebb2`) respectively.

use repr::Function;
use entities::{Inst, Ebb};
use instructions::InstructionData;
use std::collections::{BTreeSet, BTreeMap, btree_map};

/// A basic block denoted by its enclosing Ebb and last instruction.
pub type Predecessor = (Ebb, Inst);

/// Storing predecessors in a BTreeSet ensures that their ordering is
/// stable with no duplicates.
pub type PredecessorSet = BTreeSet<Predecessor>;

/// The Control Flow Graph maintains a mapping of ebbs to their predecessors
/// where predecessors are basic blocks.
#[derive(Debug)]
pub struct ControlFlowGraph {
    data: BTreeMap<Ebb, PredecessorSet>,
}

impl ControlFlowGraph {
    /// During initialization mappings will be generated for any existing
    /// blocks within the CFG's associated function. Basic sanity checks will
    /// also be performed to ensure that the blocks are well formed.
    pub fn new(func: &Function) -> Result<ControlFlowGraph, String> {
        let mut cfg = ControlFlowGraph { data: BTreeMap::new() };

        // Even ebbs without predecessors should show up in the CFG, albeit
        // with no entires.
        for ebb in func.ebbs_numerically() {
            try!(cfg.init_ebb(ebb));
        }

        for ebb in func.ebbs_numerically() {
            // Flips to true when a terminating instruction is seen. So that if additional
            // instructions occur an error may be returned.
            let mut terminated = false;
            for inst in func.ebb_insts(ebb) {
                if terminated {
                    return Err(format!("{} contains unreachable instructions.", ebb));
                }

                match func[inst] {
                    InstructionData::Branch { ty: _, opcode: _, ref data } => {
                        try!(cfg.add_predecessor(data.destination, (ebb, inst)));
                    }
                    InstructionData::Jump { ty: _, opcode: _, ref data } => {
                        try!(cfg.add_predecessor(data.destination, (ebb, inst)));
                        terminated = true;
                    }
                    InstructionData::Return { ty: _, opcode: _, data: _ } => {
                        terminated = true;
                    }
                    InstructionData::Nullary { ty: _, opcode: _ } => {
                        terminated = true;
                    }
                    _ => (),
                }
            }
        }
        Ok(cfg)
    }

    /// Initializes a predecessor set for some ebb. If an ebb already has an
    /// entry it will be clobbered.
    pub fn init_ebb(&mut self, ebb: Ebb) -> Result<&mut PredecessorSet, &'static str> {
        self.data.insert(ebb, BTreeSet::new());
        match self.data.get_mut(&ebb) {
            Some(predecessors) => Ok(predecessors),
            None => Err("Ebb initialization failed."),
        }
    }

    /// Attempts to add a predecessor for some ebb, attempting to initialize
    /// any ebb which has no entry.
    pub fn add_predecessor(&mut self,
                           ebb: Ebb,
                           predecessor: Predecessor)
                           -> Result<(), &'static str> {
        let success = match self.data.get_mut(&ebb) {
            Some(predecessors) => predecessors.insert(predecessor),
            None => false,
        };

        if success {
            Ok(())
        } else {
            let mut predecessors = try!(self.init_ebb(ebb));
            if predecessors.insert(predecessor) {
                return Ok(());
            }
            Err("Predecessor insertion failed.")
        }

    }

    /// Returns all of the predecessors for some ebb, if it has an entry.
    pub fn get_predecessors(&self, ebb: Ebb) -> Option<&PredecessorSet> {
        self.data.get(&ebb)
    }

    /// An iterator over all of the ebb to predecessor mappings in the CFG.
    pub fn iter<'a>(&'a self) -> btree_map::Iter<'a, Ebb, PredecessorSet> {
        self.data.iter()
    }
}

#[cfg(test)]
mod tests {
    use instructions::*;
    use entities::{Ebb, Inst, NO_VALUE};
    use repr::Function;
    use super::*;
    use types;

    // Some instructions will be re-used in several tests.

    fn nullary(func: &mut Function) -> Inst {
        func.make_inst(InstructionData::Nullary {
            opcode: Opcode::Iconst,
            ty: types::I32,
        })
    }

    fn jump(func: &mut Function, dest: Ebb) -> Inst {
        func.make_inst(InstructionData::Jump {
            opcode: Opcode::Jump,
            ty: types::VOID,
            data: Box::new(JumpData {
                destination: dest,
                arguments: VariableArgs::new(),
            }),
        })
    }

    fn branch(func: &mut Function, dest: Ebb) -> Inst {
        func.make_inst(InstructionData::Branch {
            opcode: Opcode::Brz,
            ty: types::VOID,
            data: Box::new(BranchData {
                arg: NO_VALUE,
                destination: dest,
                arguments: VariableArgs::new(),
            }),
        })
    }

    #[test]
    fn empty() {
        let func = Function::new();
        let cfg = ControlFlowGraph::new(&func).unwrap();
        assert_eq!(None, cfg.iter().next());
    }

    #[test]
    fn no_predecessors() {
        let mut func = Function::new();
        func.make_ebb();
        func.make_ebb();
        func.make_ebb();
        let cfg = ControlFlowGraph::new(&func).unwrap();
        let nodes = cfg.iter().collect::<Vec<_>>();
        assert_eq!(nodes.len(), 3);

        let mut fun_ebbs = func.ebbs_numerically();
        for (ebb, predecessors) in nodes {
            assert_eq!(ebb.index(), fun_ebbs.next().unwrap().index());
            assert_eq!(predecessors.len(), 0);
        }
    }

    #[test]
    #[should_panic(expected = "instructions")]
    fn nullable_before_branch() {
        // Ensure that branching after a nullary, within an ebb, triggers an error.
        let mut func = Function::new();
        let ebb0 = func.make_ebb();
        let ebb1_malformed = func.make_ebb();
        let ebb2 = func.make_ebb();

        let nullary_inst = nullary(&mut func);
        func.append_inst(ebb1_malformed, nullary_inst);

        let jmp_ebb1_ebb0 = jump(&mut func, ebb0);
        func.append_inst(ebb1_malformed, jmp_ebb1_ebb0);

        let jmp_ebb0_ebb2 = jump(&mut func, ebb2);
        func.append_inst(ebb0, jmp_ebb0_ebb2);

        ControlFlowGraph::new(&func).unwrap();
    }

    #[test]
    #[should_panic(expected = "instructions")]
    fn jump_before_branch() {
        // Ensure that branching after a jump, within an ebb, triggers an error.
        let mut func = Function::new();
        let ebb0 = func.make_ebb();
        let ebb1_malformed = func.make_ebb();
        let ebb2 = func.make_ebb();

        let jmp_ebb0_ebb1 = jump(&mut func, ebb2);
        func.append_inst(ebb0, jmp_ebb0_ebb1);

        let jmp_ebb1_ebb2 = jump(&mut func, ebb2);
        func.append_inst(ebb1_malformed, jmp_ebb1_ebb2);

        let br_ebb1_ebb0 = branch(&mut func, ebb0);
        func.append_inst(ebb1_malformed, br_ebb1_ebb0);

        ControlFlowGraph::new(&func).unwrap();
    }

    #[test]
    fn branches_and_jumps() {
        let mut func = Function::new();
        let ebb0 = func.make_ebb();
        let ebb1 = func.make_ebb();
        let ebb2 = func.make_ebb();

        let br_ebb0_ebb2 = branch(&mut func, ebb2);
        func.append_inst(ebb0, br_ebb0_ebb2);

        let jmp_ebb0_ebb1 = jump(&mut func, ebb1);
        func.append_inst(ebb0, jmp_ebb0_ebb1);

        let br_ebb1_ebb1 = branch(&mut func, ebb1);
        func.append_inst(ebb1, br_ebb1_ebb1);

        let jmp_ebb1_ebb2 = jump(&mut func, ebb2);
        func.append_inst(ebb1, jmp_ebb1_ebb2);

        let cfg = ControlFlowGraph::new(&func).unwrap();
        let ebb0_predecessors = cfg.get_predecessors(ebb0).unwrap();
        let ebb1_predecessors = cfg.get_predecessors(ebb1).unwrap();
        let ebb2_predecessors = cfg.get_predecessors(ebb2).unwrap();
        assert_eq!(ebb0_predecessors.len(), 0);
        assert_eq!(ebb1_predecessors.len(), 2);
        assert_eq!(ebb2_predecessors.len(), 2);

        assert_eq!(ebb1_predecessors.contains(&(ebb0, jmp_ebb0_ebb1)), true);
        assert_eq!(ebb1_predecessors.contains(&(ebb1, br_ebb1_ebb1)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb0, br_ebb0_ebb2)), true);
        assert_eq!(ebb2_predecessors.contains(&(ebb1, jmp_ebb1_ebb2)), true);
    }

}
<|endoftext|>


<commit_before>use core::error::FromError;
use geojson::GeoJsonError;

#[derive(Copy)]
pub struct TopoJsonError {
    pub desc: &'static str,
}

impl TopoJsonError {
    pub fn new(desc: &'static str) -> TopoJsonError {
        return TopoJsonError{desc: desc};
    }
}

impl FromError<GeoJsonError> for TopoJsonError {
    fn from_error(e: GeoJsonError) -> TopoJsonError {
        return TopoJsonError::new(e.desc);
    }
}

pub type TopoJsonResult<T> = Result<T, TopoJsonError>;
<commit_msg>Update error.rs<commit_after>use core::error::FromError;
use geojson::GeoJsonError;

#[derive(Debug, PartialEq, Eq, Copy)]
pub struct TopoJsonError {
    pub desc: &'static str,
}

impl TopoJsonError {
    pub fn new(desc: &'static str) -> TopoJsonError {
        return TopoJsonError{desc: desc};
    }
}

impl FromError<GeoJsonError> for TopoJsonError {
    fn from_error(e: GeoJsonError) -> TopoJsonError {
        return TopoJsonError::new(e.desc);
    }
}

pub type TopoJsonResult<T> = Result<T, TopoJsonError>;
<|endoftext|>


<commit_before>// Copyright 2012-2014 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 rustc_lint;
use rustc_driver::{self, driver, target_features, abort_on_err};
use rustc::session::{self, config};
use rustc::hir::def_id::{DefId, CrateNum};
use rustc::hir::def::Def;
use rustc::middle::cstore::CrateStore;
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt, AllArenas};
use rustc::hir::map as hir_map;
use rustc::lint::{self, LintPass};
use rustc::session::config::ErrorOutputType;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_resolve as resolve;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
use rustc_target::spec::TargetTriple;

use syntax::ast::NodeId;
use syntax::codemap;
use syntax::edition::Edition;
use syntax::feature_gate::UnstableFeatures;
use syntax::json::JsonEmitter;
use errors;
use errors::emitter::{Emitter, EmitterWriter};

use std::cell::{RefCell, Cell};
use std::mem;
use rustc_data_structures::sync::{self, Lrc};
use std::rc::Rc;
use std::path::PathBuf;

use visit_ast::RustdocVisitor;
use clean;
use clean::Clean;
use html::render::RenderInfo;

pub use rustc::session::config::{Input, CodegenOptions};
pub use rustc::session::search_paths::SearchPaths;

pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;

pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
    pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
    /// The stack of module NodeIds up till this point
    pub mod_ids: RefCell<Vec<NodeId>>,
    pub crate_name: Option<String>,
    pub cstore: Rc<CrateStore>,
    pub populated_all_crate_impls: Cell<bool>,
    // Note that external items for which `doc(hidden)` applies to are shown as
    // non-reachable while local items aren't. This is because we're reusing
    // the access levels from crateanalysis.
    /// Later on moved into `clean::Crate`
    pub access_levels: RefCell<AccessLevels<DefId>>,
    /// Later on moved into `html::render::CACHE_KEY`
    pub renderinfo: RefCell<RenderInfo>,
    /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
    pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
    /// Used while populating `external_traits` to ensure we don't process the same trait twice at
    /// the same time.
    pub active_extern_traits: RefCell<Vec<DefId>>,
    // The current set of type and lifetime substitutions,
    // for expanding type aliases at the HIR level:

    /// Table type parameter definition -> substituted type
    pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
    /// Table node id of lifetime parameter definition -> substituted lifetime
    pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
    /// Table DefId of `impl Trait` in argument position -> bounds
    pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
    pub send_trait: Option<DefId>,
    pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
    pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
    /// Maps (type_id, trait_id) -> auto trait impl
    pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>
}

impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
    pub fn sess(&self) -> &session::Session {
        &self.tcx.sess
    }

    /// Call the closure with the given parameters set as
    /// the substitutions for a type alias' RHS.
    pub fn enter_alias<F, R>(&self,
                             ty_substs: FxHashMap<Def, clean::Type>,
                             lt_substs: FxHashMap<DefId, clean::Lifetime>,
                             f: F) -> R
    where F: FnOnce() -> R {
        let (old_tys, old_lts) =
            (mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs),
             mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs));
        let r = f();
        *self.ty_substs.borrow_mut() = old_tys;
        *self.lt_substs.borrow_mut() = old_lts;
        r
    }
}

pub trait DocAccessLevels {
    fn is_doc_reachable(&self, did: DefId) -> bool;
}

impl DocAccessLevels for AccessLevels<DefId> {
    fn is_doc_reachable(&self, did: DefId) -> bool {
        self.is_public(did)
    }
}

/// Creates a new diagnostic `Handler` that can be used to emit warnings and errors.
///
/// If the given `error_format` is `ErrorOutputType::Json` and no `CodeMap` is given, a new one
/// will be created for the handler.
pub fn new_handler(error_format: ErrorOutputType, codemap: Option<Lrc<codemap::CodeMap>>)
    -> errors::Handler
{
    // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
    // stick to the defaults
    let sessopts = config::basic_options();
    let emitter: Box<dyn Emitter + sync::Send> = match error_format {
        ErrorOutputType::HumanReadable(color_config) => Box::new(
            EmitterWriter::stderr(
                color_config,
                codemap.map(|cm| cm as _),
                false,
                sessopts.debugging_opts.teach,
            ).ui_testing(sessopts.debugging_opts.ui_testing)
        ),
        ErrorOutputType::Json(pretty) => {
            let codemap = codemap.unwrap_or_else(
                || Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())));
            Box::new(
                JsonEmitter::stderr(
                    None,
                    codemap,
                    pretty,
                ).ui_testing(sessopts.debugging_opts.ui_testing)
            )
        },
        ErrorOutputType::Short(color_config) => Box::new(
            EmitterWriter::stderr(
                color_config,
                codemap.map(|cm| cm as _),
                true,
                false)
        ),
    };

    errors::Handler::with_emitter_and_flags(
        emitter,
        errors::HandlerFlags {
            can_emit_warnings: true,
            treat_err_as_bug: false,
            external_macro_backtrace: false,
            ..Default::default()
        },
    )
}

pub fn run_core(search_paths: SearchPaths,
                cfgs: Vec<String>,
                externs: config::Externs,
                input: Input,
                triple: Option<TargetTriple>,
                maybe_sysroot: Option<PathBuf>,
                allow_warnings: bool,
                crate_name: Option<String>,
                force_unstable_if_unmarked: bool,
                edition: Edition,
                cg: CodegenOptions,
                error_format: ErrorOutputType) -> (clean::Crate, RenderInfo)
{
    // Parse, resolve, and typecheck the given crate.

    let cpath = match input {
        Input::File(ref p) => Some(p.clone()),
        _ => None
    };

    let intra_link_resolution_failure_name = lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE.name;
    let warnings_lint_name = lint::builtin::WARNINGS.name;
    let missing_docs = rustc_lint::builtin::MISSING_DOCS.name;
    let lints = lint::builtin::HardwiredLints.get_lints()
                    .into_iter()
                    .chain(rustc_lint::SoftLints.get_lints().into_iter())
                    .filter_map(|lint| {
                        if lint.name == warnings_lint_name ||
                           lint.name == intra_link_resolution_failure_name {
                            None
                        } else {
                            Some((lint.name_lower(), lint::Allow))
                        }
                    })
                    .collect::<Vec<_>>();

    let host_triple = TargetTriple::from_triple(config::host_triple());
    // plays with error output here!
    let sessopts = config::Options {
        maybe_sysroot,
        search_paths,
        crate_types: vec![config::CrateTypeRlib],
        lint_opts: if !allow_warnings {
            lints
        } else {
            vec![]
        },
        lint_cap: Some(lint::Forbid),
        cg,
        externs,
        target_triple: triple.unwrap_or(host_triple),
        // Ensure that rustdoc works even if rustc is feature-staged
        unstable_features: UnstableFeatures::Allow,
        actually_rustdoc: true,
        debugging_opts: config::DebuggingOptions {
            force_unstable_if_unmarked,
            ..config::basic_debugging_options()
        },
        error_format,
        edition,
        ..config::basic_options()
    };
    driver::spawn_thread_pool(sessopts, move |sessopts| {
        let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
        let diagnostic_handler = new_handler(error_format, Some(codemap.clone()));

        let mut sess = session::build_session_(
            sessopts, cpath, diagnostic_handler, codemap,
        );

        lint::builtin::HardwiredLints.get_lints()
                                     .into_iter()
                                     .chain(rustc_lint::SoftLints.get_lints().into_iter())
                                     .filter_map(|lint| {
                                         if lint.name == warnings_lint_name ||
                                            lint.name == intra_link_resolution_failure_name ||
                                            lint.name == missing_docs {
                                             None
                                         } else {
                                             Some(lint)
                                         }
                                     })
                                     .for_each(|l| {
                                         sess.driver_lint_caps.insert(lint::LintId::of(l),
                                                                      lint::Allow);
                                     });

        let codegen_backend = rustc_driver::get_codegen_backend(&sess);
        let cstore = Rc::new(CStore::new(codegen_backend.metadata_loader()));
        rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

        let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
        target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
        sess.parse_sess.config = cfg;

        let control = &driver::CompileController::basic();

        let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));

        let name = match crate_name {
            Some(ref crate_name) => crate_name.clone(),
            None => ::rustc_codegen_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input),
        };

        let mut crate_loader = CrateLoader::new(&sess, &cstore, &name);

        let resolver_arenas = resolve::Resolver::arenas();
        let result = driver::phase_2_configure_and_expand_inner(&sess,
                                                        &cstore,
                                                        krate,
                                                        None,
                                                        &name,
                                                        None,
                                                        resolve::MakeGlobMap::No,
                                                        &resolver_arenas,
                                                        &mut crate_loader,
                                                        |_| Ok(()));
        let driver::InnerExpansionResult {
            mut hir_forest,
            mut resolver,
            ..
        } = abort_on_err(result, &sess);

        resolver.ignore_extern_prelude_feature = true;

        // We need to hold on to the complete resolver, so we clone everything
        // for the analysis passes to use. Suboptimal, but necessary in the
        // current architecture.
        let defs = resolver.definitions.clone();
        let resolutions = ty::Resolutions {
            freevars: resolver.freevars.clone(),
            export_map: resolver.export_map.clone(),
            trait_map: resolver.trait_map.clone(),
            maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
            maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
        };
        let analysis = ty::CrateAnalysis {
            access_levels: Lrc::new(AccessLevels::default()),
            name: name.to_string(),
            glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None },
        };

        let arenas = AllArenas::new();
        let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
        let output_filenames = driver::build_output_filenames(&input,
                                                            &None,
                                                            &None,
                                                            &[],
                                                            &sess);

        let resolver = RefCell::new(resolver);
        abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend,
                                                        control,
                                                        &sess,
                                                        &*cstore,
                                                        hir_map,
                                                        analysis,
                                                        resolutions,
                                                        &arenas,
                                                        &name,
                                                        &output_filenames,
                                                        |tcx, analysis, _, result| {
            if let Err(_) = result {
                sess.fatal("Compilation failed, aborting rustdoc");
            }

            let ty::CrateAnalysis { access_levels, .. } = analysis;

            // Convert from a NodeId set to a DefId set since we don't always have easy access
            // to the map from defid -> nodeid
            let access_levels = AccessLevels {
                map: access_levels.map.iter()
                                    .map(|(&k, &v)| (tcx.hir.local_def_id(k), v))
                                    .collect()
            };

            let send_trait = if crate_name == Some("core".to_string()) {
                clean::get_trait_def_id(&tcx, &["marker", "Send"], true)
            } else {
                clean::get_trait_def_id(&tcx, &["core", "marker", "Send"], false)
            };

            let ctxt = DocContext {
                tcx,
                resolver: &resolver,
                crate_name,
                cstore: cstore.clone(),
                populated_all_crate_impls: Cell::new(false),
                access_levels: RefCell::new(access_levels),
                external_traits: Default::default(),
                active_extern_traits: Default::default(),
                renderinfo: Default::default(),
                ty_substs: Default::default(),
                lt_substs: Default::default(),
                impl_trait_bounds: Default::default(),
                mod_ids: Default::default(),
                send_trait: send_trait,
                fake_def_ids: RefCell::new(FxHashMap()),
                all_fake_def_ids: RefCell::new(FxHashSet()),
                generated_synthetics: RefCell::new(FxHashSet()),
            };
            debug!("crate: {:?}", tcx.hir.krate());

            let krate = {
                let mut v = RustdocVisitor::new(&*cstore, &ctxt);
                v.visit(tcx.hir.krate());
                v.clean(&ctxt)
            };

            (krate, ctxt.renderinfo.into_inner())
        }), &sess)
    })
}
<commit_msg>add comment about lints whitelisting<commit_after>// Copyright 2012-2014 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 rustc_lint;
use rustc_driver::{self, driver, target_features, abort_on_err};
use rustc::session::{self, config};
use rustc::hir::def_id::{DefId, CrateNum};
use rustc::hir::def::Def;
use rustc::middle::cstore::CrateStore;
use rustc::middle::privacy::AccessLevels;
use rustc::ty::{self, TyCtxt, AllArenas};
use rustc::hir::map as hir_map;
use rustc::lint::{self, LintPass};
use rustc::session::config::ErrorOutputType;
use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_resolve as resolve;
use rustc_metadata::creader::CrateLoader;
use rustc_metadata::cstore::CStore;
use rustc_target::spec::TargetTriple;

use syntax::ast::NodeId;
use syntax::codemap;
use syntax::edition::Edition;
use syntax::feature_gate::UnstableFeatures;
use syntax::json::JsonEmitter;
use errors;
use errors::emitter::{Emitter, EmitterWriter};

use std::cell::{RefCell, Cell};
use std::mem;
use rustc_data_structures::sync::{self, Lrc};
use std::rc::Rc;
use std::path::PathBuf;

use visit_ast::RustdocVisitor;
use clean;
use clean::Clean;
use html::render::RenderInfo;

pub use rustc::session::config::{Input, CodegenOptions};
pub use rustc::session::search_paths::SearchPaths;

pub type ExternalPaths = FxHashMap<DefId, (Vec<String>, clean::TypeKind)>;

pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
    pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
    /// The stack of module NodeIds up till this point
    pub mod_ids: RefCell<Vec<NodeId>>,
    pub crate_name: Option<String>,
    pub cstore: Rc<CrateStore>,
    pub populated_all_crate_impls: Cell<bool>,
    // Note that external items for which `doc(hidden)` applies to are shown as
    // non-reachable while local items aren't. This is because we're reusing
    // the access levels from crateanalysis.
    /// Later on moved into `clean::Crate`
    pub access_levels: RefCell<AccessLevels<DefId>>,
    /// Later on moved into `html::render::CACHE_KEY`
    pub renderinfo: RefCell<RenderInfo>,
    /// Later on moved through `clean::Crate` into `html::render::CACHE_KEY`
    pub external_traits: RefCell<FxHashMap<DefId, clean::Trait>>,
    /// Used while populating `external_traits` to ensure we don't process the same trait twice at
    /// the same time.
    pub active_extern_traits: RefCell<Vec<DefId>>,
    // The current set of type and lifetime substitutions,
    // for expanding type aliases at the HIR level:

    /// Table type parameter definition -> substituted type
    pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
    /// Table node id of lifetime parameter definition -> substituted lifetime
    pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
    /// Table DefId of `impl Trait` in argument position -> bounds
    pub impl_trait_bounds: RefCell<FxHashMap<DefId, Vec<clean::GenericBound>>>,
    pub send_trait: Option<DefId>,
    pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
    pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
    /// Maps (type_id, trait_id) -> auto trait impl
    pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>
}

impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
    pub fn sess(&self) -> &session::Session {
        &self.tcx.sess
    }

    /// Call the closure with the given parameters set as
    /// the substitutions for a type alias' RHS.
    pub fn enter_alias<F, R>(&self,
                             ty_substs: FxHashMap<Def, clean::Type>,
                             lt_substs: FxHashMap<DefId, clean::Lifetime>,
                             f: F) -> R
    where F: FnOnce() -> R {
        let (old_tys, old_lts) =
            (mem::replace(&mut *self.ty_substs.borrow_mut(), ty_substs),
             mem::replace(&mut *self.lt_substs.borrow_mut(), lt_substs));
        let r = f();
        *self.ty_substs.borrow_mut() = old_tys;
        *self.lt_substs.borrow_mut() = old_lts;
        r
    }
}

pub trait DocAccessLevels {
    fn is_doc_reachable(&self, did: DefId) -> bool;
}

impl DocAccessLevels for AccessLevels<DefId> {
    fn is_doc_reachable(&self, did: DefId) -> bool {
        self.is_public(did)
    }
}

/// Creates a new diagnostic `Handler` that can be used to emit warnings and errors.
///
/// If the given `error_format` is `ErrorOutputType::Json` and no `CodeMap` is given, a new one
/// will be created for the handler.
pub fn new_handler(error_format: ErrorOutputType, codemap: Option<Lrc<codemap::CodeMap>>)
    -> errors::Handler
{
    // rustdoc doesn't override (or allow to override) anything from this that is relevant here, so
    // stick to the defaults
    let sessopts = config::basic_options();
    let emitter: Box<dyn Emitter + sync::Send> = match error_format {
        ErrorOutputType::HumanReadable(color_config) => Box::new(
            EmitterWriter::stderr(
                color_config,
                codemap.map(|cm| cm as _),
                false,
                sessopts.debugging_opts.teach,
            ).ui_testing(sessopts.debugging_opts.ui_testing)
        ),
        ErrorOutputType::Json(pretty) => {
            let codemap = codemap.unwrap_or_else(
                || Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())));
            Box::new(
                JsonEmitter::stderr(
                    None,
                    codemap,
                    pretty,
                ).ui_testing(sessopts.debugging_opts.ui_testing)
            )
        },
        ErrorOutputType::Short(color_config) => Box::new(
            EmitterWriter::stderr(
                color_config,
                codemap.map(|cm| cm as _),
                true,
                false)
        ),
    };

    errors::Handler::with_emitter_and_flags(
        emitter,
        errors::HandlerFlags {
            can_emit_warnings: true,
            treat_err_as_bug: false,
            external_macro_backtrace: false,
            ..Default::default()
        },
    )
}

pub fn run_core(search_paths: SearchPaths,
                cfgs: Vec<String>,
                externs: config::Externs,
                input: Input,
                triple: Option<TargetTriple>,
                maybe_sysroot: Option<PathBuf>,
                allow_warnings: bool,
                crate_name: Option<String>,
                force_unstable_if_unmarked: bool,
                edition: Edition,
                cg: CodegenOptions,
                error_format: ErrorOutputType) -> (clean::Crate, RenderInfo)
{
    // Parse, resolve, and typecheck the given crate.

    let cpath = match input {
        Input::File(ref p) => Some(p.clone()),
        _ => None
    };

    let intra_link_resolution_failure_name = lint::builtin::INTRA_DOC_LINK_RESOLUTION_FAILURE.name;
    let warnings_lint_name = lint::builtin::WARNINGS.name;
    let missing_docs = rustc_lint::builtin::MISSING_DOCS.name;
    let lints = lint::builtin::HardwiredLints.get_lints()
                    .into_iter()
                    .chain(rustc_lint::SoftLints.get_lints().into_iter())
                    .filter_map(|lint| {
                        if lint.name == warnings_lint_name ||
                           lint.name == intra_link_resolution_failure_name {
                            None
                        } else {
                            Some((lint.name_lower(), lint::Allow))
                        }
                    })
                    .collect::<Vec<_>>();

    let host_triple = TargetTriple::from_triple(config::host_triple());
    // plays with error output here!
    let sessopts = config::Options {
        maybe_sysroot,
        search_paths,
        crate_types: vec![config::CrateTypeRlib],
        lint_opts: if !allow_warnings {
            lints
        } else {
            vec![]
        },
        lint_cap: Some(lint::Forbid),
        cg,
        externs,
        target_triple: triple.unwrap_or(host_triple),
        // Ensure that rustdoc works even if rustc is feature-staged
        unstable_features: UnstableFeatures::Allow,
        actually_rustdoc: true,
        debugging_opts: config::DebuggingOptions {
            force_unstable_if_unmarked,
            ..config::basic_debugging_options()
        },
        error_format,
        edition,
        ..config::basic_options()
    };
    driver::spawn_thread_pool(sessopts, move |sessopts| {
        let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
        let diagnostic_handler = new_handler(error_format, Some(codemap.clone()));

        let mut sess = session::build_session_(
            sessopts, cpath, diagnostic_handler, codemap,
        );

        lint::builtin::HardwiredLints.get_lints()
                                     .into_iter()
                                     .chain(rustc_lint::SoftLints.get_lints().into_iter())
                                     .filter_map(|lint| {
                                         // We don't want to whitelist *all* lints so let's
                                         // ignore those ones.
                                         if lint.name == warnings_lint_name ||
                                            lint.name == intra_link_resolution_failure_name ||
                                            lint.name == missing_docs {
                                             None
                                         } else {
                                             Some(lint)
                                         }
                                     })
                                     .for_each(|l| {
                                         sess.driver_lint_caps.insert(lint::LintId::of(l),
                                                                      lint::Allow);
                                     });

        let codegen_backend = rustc_driver::get_codegen_backend(&sess);
        let cstore = Rc::new(CStore::new(codegen_backend.metadata_loader()));
        rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));

        let mut cfg = config::build_configuration(&sess, config::parse_cfgspecs(cfgs));
        target_features::add_configuration(&mut cfg, &sess, &*codegen_backend);
        sess.parse_sess.config = cfg;

        let control = &driver::CompileController::basic();

        let krate = panictry!(driver::phase_1_parse_input(control, &sess, &input));

        let name = match crate_name {
            Some(ref crate_name) => crate_name.clone(),
            None => ::rustc_codegen_utils::link::find_crate_name(Some(&sess), &krate.attrs, &input),
        };

        let mut crate_loader = CrateLoader::new(&sess, &cstore, &name);

        let resolver_arenas = resolve::Resolver::arenas();
        let result = driver::phase_2_configure_and_expand_inner(&sess,
                                                        &cstore,
                                                        krate,
                                                        None,
                                                        &name,
                                                        None,
                                                        resolve::MakeGlobMap::No,
                                                        &resolver_arenas,
                                                        &mut crate_loader,
                                                        |_| Ok(()));
        let driver::InnerExpansionResult {
            mut hir_forest,
            mut resolver,
            ..
        } = abort_on_err(result, &sess);

        resolver.ignore_extern_prelude_feature = true;

        // We need to hold on to the complete resolver, so we clone everything
        // for the analysis passes to use. Suboptimal, but necessary in the
        // current architecture.
        let defs = resolver.definitions.clone();
        let resolutions = ty::Resolutions {
            freevars: resolver.freevars.clone(),
            export_map: resolver.export_map.clone(),
            trait_map: resolver.trait_map.clone(),
            maybe_unused_trait_imports: resolver.maybe_unused_trait_imports.clone(),
            maybe_unused_extern_crates: resolver.maybe_unused_extern_crates.clone(),
        };
        let analysis = ty::CrateAnalysis {
            access_levels: Lrc::new(AccessLevels::default()),
            name: name.to_string(),
            glob_map: if resolver.make_glob_map { Some(resolver.glob_map.clone()) } else { None },
        };

        let arenas = AllArenas::new();
        let hir_map = hir_map::map_crate(&sess, &*cstore, &mut hir_forest, &defs);
        let output_filenames = driver::build_output_filenames(&input,
                                                            &None,
                                                            &None,
                                                            &[],
                                                            &sess);

        let resolver = RefCell::new(resolver);
        abort_on_err(driver::phase_3_run_analysis_passes(&*codegen_backend,
                                                        control,
                                                        &sess,
                                                        &*cstore,
                                                        hir_map,
                                                        analysis,
                                                        resolutions,
                                                        &arenas,
                                                        &name,
                                                        &output_filenames,
                                                        |tcx, analysis, _, result| {
            if let Err(_) = result {
                sess.fatal("Compilation failed, aborting rustdoc");
            }

            let ty::CrateAnalysis { access_levels, .. } = analysis;

            // Convert from a NodeId set to a DefId set since we don't always have easy access
            // to the map from defid -> nodeid
            let access_levels = AccessLevels {
                map: access_levels.map.iter()
                                    .map(|(&k, &v)| (tcx.hir.local_def_id(k), v))
                                    .collect()
            };

            let send_trait = if crate_name == Some("core".to_string()) {
                clean::get_trait_def_id(&tcx, &["marker", "Send"], true)
            } else {
                clean::get_trait_def_id(&tcx, &["core", "marker", "Send"], false)
            };

            let ctxt = DocContext {
                tcx,
                resolver: &resolver,
                crate_name,
                cstore: cstore.clone(),
                populated_all_crate_impls: Cell::new(false),
                access_levels: RefCell::new(access_levels),
                external_traits: Default::default(),
                active_extern_traits: Default::default(),
                renderinfo: Default::default(),
                ty_substs: Default::default(),
                lt_substs: Default::default(),
                impl_trait_bounds: Default::default(),
                mod_ids: Default::default(),
                send_trait: send_trait,
                fake_def_ids: RefCell::new(FxHashMap()),
                all_fake_def_ids: RefCell::new(FxHashSet()),
                generated_synthetics: RefCell::new(FxHashSet()),
            };
            debug!("crate: {:?}", tcx.hir.krate());

            let krate = {
                let mut v = RustdocVisitor::new(&*cstore, &ctxt);
                v.visit(tcx.hir.krate());
                v.clean(&ctxt)
            };

            (krate, ctxt.renderinfo.into_inner())
        }), &sess)
    })
}
<|endoftext|>


<commit_before>// Copyright 2014 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.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! bitflags!(Flags: u32 {
//!     FlagA       = 0x00000001,
//!     FlagB       = 0x00000010,
//!     FlagC       = 0x00000100,
//!     FlagABC     = FlagA.bits
//!                 | FlagB.bits
//!                 | FlagC.bits
//! })
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! use std::fmt;
//!
//! bitflags!(Flags: u32 {
//!     FlagA   = 0x00000001,
//!     FlagB   = 0x00000010
//! })
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f.buf, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags), ~"hi!");
//! }
//! ~~~
//!
//! # Derived traits
//!
//! The `Eq`, `TotalEq`, and `Clone` traits are automatically derived for the
//! `struct` using the `deriving` attribute.
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#[macro_export]
macro_rules! bitflags(
    ($BitFlags:ident: $T:ty {
        $($Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        pub struct $BitFlags {
            priv bits: $T,
        }

        $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    use ops::{BitOr, BitAnd, Sub};

    bitflags!(Flags: u32 {
        FlagA       = 0x00000001,
        FlagB       = 0x00000010,
        FlagC       = 0x00000100,
        FlagABC     = FlagA.bits
                    | FlagB.bits
                    | FlagC.bits
    })

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<commit_msg>Update for language changes<commit_after>// Copyright 2014 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.

//! The `bitflags!` macro generates a `struct` that holds a set of C-style
//! bitmask flags. It is useful for creating typesafe wrappers for C APIs.
//!
//! The flags should only be defined for integer types, otherwise unexpected
//! type errors may occur at compile time.
//!
//! # Example
//!
//! ~~~rust
//! bitflags!(Flags: u32 {
//!     FlagA       = 0x00000001,
//!     FlagB       = 0x00000010,
//!     FlagC       = 0x00000100,
//!     FlagABC     = FlagA.bits
//!                 | FlagB.bits
//!                 | FlagC.bits
//! })
//!
//! fn main() {
//!     let e1 = FlagA | FlagC;
//!     let e2 = FlagB | FlagC;
//!     assert!((e1 | e2) == FlagABC);   // union
//!     assert!((e1 & e2) == FlagC);     // intersection
//!     assert!((e1 - e2) == FlagA);     // set difference
//! }
//! ~~~
//!
//! The generated `struct`s can also be extended with type and trait implementations:
//!
//! ~~~rust
//! use std::fmt;
//!
//! bitflags!(Flags: u32 {
//!     FlagA   = 0x00000001,
//!     FlagB   = 0x00000010
//! })
//!
//! impl Flags {
//!     pub fn clear(&mut self) {
//!         self.bits = 0;  // The `bits` field can be accessed from within the
//!                         // same module where the `bitflags!` macro was invoked.
//!     }
//! }
//!
//! impl fmt::Show for Flags {
//!     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
//!         write!(f.buf, "hi!")
//!     }
//! }
//!
//! fn main() {
//!     let mut flags = FlagA | FlagB;
//!     flags.clear();
//!     assert!(flags.is_empty());
//!     assert_eq!(format!("{}", flags), ~"hi!");
//! }
//! ~~~
//!
//! # Derived traits
//!
//! The `Eq`, `TotalEq`, and `Clone` traits are automatically derived for the
//! `struct` using the `deriving` attribute.
//!
//! # Operators
//!
//! The following operator traits are implemented for the generated `struct`:
//!
//! - `BitOr`: union
//! - `BitAnd`: intersection
//! - `Sub`: set difference
//!
//! # Methods
//!
//! The following methods are defined for the generated `struct`:
//!
//! - `empty`: an empty set of flags
//! - `bits`: the raw value of the flags currently stored
//! - `is_empty`: `true` if no flags are currently stored
//! - `intersects`: `true` if there are flags common to both `self` and `other`
//! - `contains`: `true` all of the flags in `other` are contained within `self`
//! - `insert`: inserts the specified flags in-place
//! - `remove`: removes the specified flags in-place

#[macro_export]
macro_rules! bitflags(
    ($BitFlags:ident: $T:ty {
        $($Flag:ident = $value:expr),+
    }) => (
        #[deriving(Eq, TotalEq, Clone)]
        pub struct $BitFlags {
            bits: $T,
        }

        $(pub static $Flag: $BitFlags = $BitFlags { bits: $value };)+

        impl $BitFlags {
            /// Returns an empty set of flags.
            pub fn empty() -> $BitFlags {
                $BitFlags { bits: 0 }
            }

            /// Returns the raw value of the flags currently stored.
            pub fn bits(&self) -> $T {
                self.bits
            }

            /// Returns `true` if no flags are currently stored.
            pub fn is_empty(&self) -> bool {
                *self == $BitFlags::empty()
            }

            /// Returns `true` if there are flags common to both `self` and `other`.
            pub fn intersects(&self, other: $BitFlags) -> bool {
                !(self & other).is_empty()
            }

            /// Returns `true` all of the flags in `other` are contained within `self`.
            pub fn contains(&self, other: $BitFlags) -> bool {
                (self & other) == other
            }

            /// Inserts the specified flags in-place.
            pub fn insert(&mut self, other: $BitFlags) {
                self.bits |= other.bits;
            }

            /// Removes the specified flags in-place.
            pub fn remove(&mut self, other: $BitFlags) {
                self.bits &= !other.bits;
            }
        }

        impl BitOr<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the union of the two sets of flags.
            #[inline]
            fn bitor(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits | other.bits }
            }
        }

        impl BitAnd<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the intersection between the two sets of flags.
            #[inline]
            fn bitand(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & other.bits }
            }
        }

        impl Sub<$BitFlags, $BitFlags> for $BitFlags {
            /// Returns the set difference of the two sets of flags.
            #[inline]
            fn sub(&self, other: &$BitFlags) -> $BitFlags {
                $BitFlags { bits: self.bits & !other.bits }
            }
        }
    )
)

#[cfg(test)]
mod tests {
    use ops::{BitOr, BitAnd, Sub};

    bitflags!(Flags: u32 {
        FlagA       = 0x00000001,
        FlagB       = 0x00000010,
        FlagC       = 0x00000100,
        FlagABC     = FlagA.bits
                    | FlagB.bits
                    | FlagC.bits
    })

    #[test]
    fn test_bits(){
        assert_eq!(Flags::empty().bits(), 0x00000000);
        assert_eq!(FlagA.bits(), 0x00000001);
        assert_eq!(FlagABC.bits(), 0x00000111);
    }

    #[test]
    fn test_is_empty(){
        assert!(Flags::empty().is_empty());
        assert!(!FlagA.is_empty());
        assert!(!FlagABC.is_empty());
    }

    #[test]
    fn test_two_empties_do_not_intersect() {
        let e1 = Flags::empty();
        let e2 = Flags::empty();
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_empty_does_not_intersect_with_full() {
        let e1 = Flags::empty();
        let e2 = FlagABC;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_disjoint_intersects() {
        let e1 = FlagA;
        let e2 = FlagB;
        assert!(!e1.intersects(e2));
    }

    #[test]
    fn test_overlapping_intersects() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(e1.intersects(e2));
    }

    #[test]
    fn test_contains() {
        let e1 = FlagA;
        let e2 = FlagA | FlagB;
        assert!(!e1.contains(e2));
        assert!(e2.contains(e1));
        assert!(FlagABC.contains(e2));
    }

    #[test]
    fn test_insert(){
        let mut e1 = FlagA;
        let e2 = FlagA | FlagB;
        e1.insert(e2);
        assert!(e1 == e2);
    }

    #[test]
    fn test_remove(){
        let mut e1 = FlagA | FlagB;
        let e2 = FlagA | FlagC;
        e1.remove(e2);
        assert!(e1 == FlagB);
    }

    #[test]
    fn test_operators() {
        let e1 = FlagA | FlagC;
        let e2 = FlagB | FlagC;
        assert!((e1 | e2) == FlagABC);   // union
        assert!((e1 & e2) == FlagC);     // intersection
        assert!((e1 - e2) == FlagA);     // set difference
    }
}
<|endoftext|>