<commit_before>use std::collections::VecDeque;
use ordered_vec_map::InsertionResult;
use disambiguation_map::{DisambiguationMap, Match};
use termion::event::{Key, parse_event};
use op::{NormalOp, InsertOp};
use std::cmp::{min, max};
use std::cmp::Ordering;

/// By convention:
/// * K is a map's key type, implementing `Copy` and `Ord`.
/// * T is an arbitrary type, typically stored as a value in a map.
/// * Op is an arbitrary operation type (typically a mode-specific enum).
#[derive(Debug, PartialEq)]
pub enum OpErr {
    EmptyKey,
    NotEnoughArgs(usize),
}

#[derive(Debug, PartialEq)]
pub enum RemapErr {
    EmptyKey,
    KeyValueEqual,
}

pub struct ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
    Op: Copy,
{
    remap_map: DisambiguationMap<K, Vec<K>>,
    op_map: DisambiguationMap<K, Op>,
}

impl<K, Op> ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
    Op: Copy,
{
    pub fn new() -> Self {
        ModeMap {
            remap_map: DisambiguationMap::new(),
            op_map: DisambiguationMap::new(),
        }
    }

    /// Process a typeahead buffer.
    pub fn process(&self, mut typeahead: &mut VecDeque<K>) -> Option<Op> {
        // Grab keys from the front of the queue, looking for matches.
        let mut i: usize = 0;
        const MAX_REMAP_ITERATIONS: usize = 1000;
        while typeahead.len() > 0 {
            if i > MAX_REMAP_ITERATIONS {
                panic!("Infinite loop suspected.");
            }
            i += 1;

            match self.remap_map.process(&mut typeahead) {
                Match::FullMatch(mapped) => {
                    let len = min(mapped.0.len(), typeahead.len());
                    typeahead.drain(..len);
                    for k in mapped.1.iter() {
                        typeahead.push_front(*k);
                    }
                }
                Match::PartialMatch => {
                    // No remapping or op mapping can occur yet.
                    return None;
                }
                Match::NoMatch => {
                    // Start searching Op map.
                    break;
                }
            }
        }
        match self.op_map.process(&mut typeahead) {
            Match::FullMatch(mapped) => {
                let len = min(mapped.0.len(), typeahead.len());
                typeahead.drain(..len);
                return Some(mapped.1);
            }
            Match::PartialMatch => {
                // No op mapping can occur yet.
                return None;
            }
            Match::NoMatch => {
                // We're done searching.
                return None;
            }
        }
    }

    /// Insert a mapping from `key` to `value` in the operations map.
    /// Empty `key`s are not allowed.
    pub fn insert_op(
        &mut self,
        key: Vec<K>,
        value: Op,
    ) -> Result<InsertionResult, OpErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(OpErr::EmptyKey);
        }
        return Ok(self.op_map.insert((key, value)));
    }

    /// Insert a mapping from `key` to `value` in the remap map.
    /// Empty `key`s are not allowed.
    /// Pairs such that `key` and `value` are equal are not allowed.
    pub fn insert_remap(
        &mut self,
        key: Vec<K>,
        value: Vec<K>,
    ) -> Result<InsertionResult, RemapErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(RemapErr::EmptyKey);
        }
        if key.cmp(&value) == Ordering::Equal {
            return Err(RemapErr::KeyValueEqual);
        }
        return Ok(self.remap_map.insert((key, value)));
    }
}

#[cfg(test)]
mod mode_map {
    use super::*;

    #[derive(Copy, Clone, Debug, PartialEq)]
    enum TestOp {
        ThingOne,
        ThingTwo,
    }

    #[test]
    fn insert_overwrite() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Overwrite),
            mode_map.insert_op(vec![1u8], TestOp::ThingTwo)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Overwrite),
            mode_map.insert_remap(vec![1u8], vec![3u8])
        );
    }

    #[test]
    fn insert_empty_key() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Err(OpErr::EmptyKey),
            mode_map.insert_op(Vec::<u8>::new(), TestOp::ThingOne)
        );
        assert_eq!(
            Err(RemapErr::EmptyKey),
            mode_map.insert_remap(Vec::<u8>::new(), vec![1u8])
        );
    }

    #[test]
    fn insert_key_value_parity() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Err(RemapErr::KeyValueEqual),
            mode_map.insert_remap(vec![1u8], vec![1u8])
        );
    }

    #[test]
    fn process_one_op() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn process_two_ops() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![2u8], TestOp::ThingTwo)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(2u8);

        assert_eq!(Some(TestOp::ThingTwo), mode_map.process(&mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn process_overspecified_full_match() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);
        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
    }

    #[test]
    fn process_put_back_leftovers() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(Some(2u8), typeahead.pop_front());
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_overspecified_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8, 1u8], vec![2u8])
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_shadow_op_with_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![2u8], TestOp::ThingTwo)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingTwo), mode_map.process(&mut typeahead));
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_remap_then_op() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![2u8], TestOp::ThingTwo)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingTwo), mode_map.process(&mut typeahead));
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_ambiguous_sequence() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();

        // Ambiguous sequence.
        typeahead.push_back(1u8);
        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(1, typeahead.len());
    }

    #[test]
    fn process_disambiguated_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();

        // Disambiguate for remap.
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);
        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(Some(2u8), typeahead.pop_front());
        assert_eq!(0, typeahead.len());
    }

    #[test]
    fn process_disambiguated_op() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();

        // Disambiguated sequence for op.
        typeahead.push_back(1u8); // Processing just this will result in None.
        typeahead.push_back(2u8); // This one disambiguates, so the op can map.
        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
        assert_eq!(Some(2u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    // Test that infinite recursion eventuates in a panic.
    // TODO Instead of panic, consider returning a special InfRecursion op
    // so we can tell the user.
    #[test]
    #[should_panic]
    fn process_inf_recursion() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![2u8], vec![1u8])
        );
        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        mode_map.process(&mut typeahead);
    }
}
<commit_msg>fix op/remap ambiguity<commit_after>use std::collections::VecDeque;
use ordered_vec_map::InsertionResult;
use disambiguation_map::{DisambiguationMap, Match};
use termion::event::{Key, parse_event};
use op::{NormalOp, InsertOp};
use std::cmp::{min, max};
use std::cmp::Ordering;

/// By convention:
/// * K is a map's key type, implementing `Copy` and `Ord`.
/// * T is an arbitrary type, typically stored as a value in a map.
/// * Op is an arbitrary operation type (typically a mode-specific enum).
#[derive(Debug, PartialEq)]
pub enum OpErr {
    EmptyKey,
    NotEnoughArgs(usize),
}

#[derive(Debug, PartialEq)]
pub enum RemapErr {
    EmptyKey,
    KeyValueEqual,
}

pub struct ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
    Op: Copy,
{
    remap_map: DisambiguationMap<K, Vec<K>>,
    op_map: DisambiguationMap<K, Op>,
}

impl<K, Op> ModeMap<K, Op>
where
    K: Ord,
    K: Copy,
    Op: Copy,
{
    pub fn new() -> Self {
        ModeMap {
            remap_map: DisambiguationMap::new(),
            op_map: DisambiguationMap::new(),
        }
    }

    /// Process a typeahead buffer.
    pub fn process(&self, mut typeahead: &mut VecDeque<K>) -> Option<Op> {
        // Grab keys from the front of the queue, looking for matches.
        let mut i: usize = 0;
        const MAX_REMAP_ITERATIONS: usize = 1000;
        while typeahead.len() > 0 {
            if i > MAX_REMAP_ITERATIONS {
                panic!("Infinite loop suspected.");
            }
            i += 1;

            let remap_result = self.remap_map.process(&mut typeahead);
            let op_result = self.op_map.process(&mut typeahead);

            match (remap_result, op_result) {
                (Match::PartialMatch, _) |
                (_, Match::PartialMatch) => {
                    // Ambiguous results.
                    break;
                }
                (Match::FullMatch(mapped), _) => {
                    // Remapping takes precedence over op-mapping.
                    let len = min(mapped.0.len(), typeahead.len());
                    typeahead.drain(..len);
                    for k in mapped.1.iter() {
                        typeahead.push_front(*k);
                    }
                }
                (Match::NoMatch, Match::FullMatch(mapped)) => {
                    // If no remapping, try op-mapping.
                    let len = min(mapped.0.len(), typeahead.len());
                    typeahead.drain(..len);
                    return Some(mapped.1);
                }
                (Match::NoMatch, Match::NoMatch) => {
                    // No matches found.
                    break;
                }
            }
        }
        return None;
    }

    /// Insert a mapping from `key` to `value` in the operations map.
    /// Empty `key`s are not allowed.
    pub fn insert_op(
        &mut self,
        key: Vec<K>,
        value: Op,
    ) -> Result<InsertionResult, OpErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(OpErr::EmptyKey);
        }
        return Ok(self.op_map.insert((key, value)));
    }

    /// Insert a mapping from `key` to `value` in the remap map.
    /// Empty `key`s are not allowed.
    /// Pairs such that `key` and `value` are equal are not allowed.
    pub fn insert_remap(
        &mut self,
        key: Vec<K>,
        value: Vec<K>,
    ) -> Result<InsertionResult, RemapErr> {
        // Disallow empty keys, as they would full-match against an empty
        // typeahead buffer.
        if key.is_empty() {
            return Err(RemapErr::EmptyKey);
        }
        if key.cmp(&value) == Ordering::Equal {
            return Err(RemapErr::KeyValueEqual);
        }
        return Ok(self.remap_map.insert((key, value)));
    }
}

#[cfg(test)]
mod mode_map {
    use super::*;

    #[derive(Copy, Clone, Debug, PartialEq)]
    enum TestOp {
        ThingOne,
        ThingTwo,
    }

    #[test]
    fn insert_overwrite() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Overwrite),
            mode_map.insert_op(vec![1u8], TestOp::ThingTwo)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Overwrite),
            mode_map.insert_remap(vec![1u8], vec![3u8])
        );
    }

    #[test]
    fn insert_empty_key() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Err(OpErr::EmptyKey),
            mode_map.insert_op(Vec::<u8>::new(), TestOp::ThingOne)
        );
        assert_eq!(
            Err(RemapErr::EmptyKey),
            mode_map.insert_remap(Vec::<u8>::new(), vec![1u8])
        );
    }

    #[test]
    fn insert_key_value_parity() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Err(RemapErr::KeyValueEqual),
            mode_map.insert_remap(vec![1u8], vec![1u8])
        );
    }

    #[test]
    fn process_one_op() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn process_two_ops() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![2u8], TestOp::ThingTwo)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(2u8);

        assert_eq!(Some(TestOp::ThingTwo), mode_map.process(&mut typeahead));
        assert!(typeahead.is_empty());
    }

    #[test]
    fn process_overspecified_full_match() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);
        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
    }

    #[test]
    fn process_put_back_leftovers() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(Some(2u8), typeahead.pop_front());
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_overspecified_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8, 1u8], vec![2u8])
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_shadow_op_with_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![2u8], TestOp::ThingTwo)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingTwo), mode_map.process(&mut typeahead));
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_remap_then_op() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![2u8], TestOp::ThingTwo)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        assert_eq!(Some(TestOp::ThingTwo), mode_map.process(&mut typeahead));
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_op_remap_ambiguate() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8, 1u8, 1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);

        // In this test, we expect the remap not to take place since we haven't
        // yet disambiguated it from the op.
        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(Some(1u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    #[test]
    fn process_ambiguous_sequence() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();

        // Ambiguous sequence.
        typeahead.push_back(1u8);
        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(1, typeahead.len());
    }

    #[test]
    fn process_disambiguated_remap() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();

        // Disambiguate for remap.
        typeahead.push_back(1u8);
        typeahead.push_back(1u8);
        assert_eq!(None, mode_map.process(&mut typeahead));
        assert_eq!(Some(2u8), typeahead.pop_front());
        assert_eq!(0, typeahead.len());
    }

    #[test]
    fn process_disambiguated_op() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8, 1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_op(vec![1u8], TestOp::ThingOne)
        );

        let mut typeahead = VecDeque::<u8>::new();

        // Disambiguated sequence for op.
        typeahead.push_back(1u8); // Processing just this will result in None.
        typeahead.push_back(2u8); // This one disambiguates, so the op can map.
        assert_eq!(Some(TestOp::ThingOne), mode_map.process(&mut typeahead));
        assert_eq!(Some(2u8), typeahead.pop_front());
        assert_eq!(None, typeahead.pop_front());
    }

    // Test that infinite recursion eventuates in a panic.
    // TODO Instead of panic, consider returning a special InfRecursion op
    // so we can tell the user.
    #[test]
    #[should_panic]
    fn process_inf_recursion() {
        let mut mode_map = ModeMap::<u8, TestOp>::new();
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![1u8], vec![2u8])
        );
        assert_eq!(
            Ok(InsertionResult::Create),
            mode_map.insert_remap(vec![2u8], vec![1u8])
        );
        let mut typeahead = VecDeque::<u8>::new();
        typeahead.push_back(1u8);
        mode_map.process(&mut typeahead);
    }
}
<|endoftext|>


<commit_before>use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::{Arc, Mutex, RwLock};
use std::sync::mpsc::{channel, Sender};
use std::time::Duration;
use std::thread;

use ::test_util::{TEST_SLEEP_TIME_MILLIS, start_log_once, Tattle};

#[test]
fn check_controller_channel_runs() {
    start_log_once();
    let (tx, rx): (Sender<super::ControllerMessage>, _) = channel();
    let controller_raw = Arc::new(super::ControllerRaw {
        connections: RwLock::new(Vec::new()),
        tx: Mutex::new(tx),
    });
    let controller_raw_clone = controller_raw.clone();
    thread::spawn(move || super::check_controller_channel(rx, controller_raw_clone));
    let tattle = Tattle::new();
    tattle.assert_changed(|| {
        controller_raw.tx.lock().unwrap().send(super::ControllerMessage::Test(tattle.clone())).unwrap();
        thread::sleep(Duration::from_millis(TEST_SLEEP_TIME_MILLIS));
    });
}

#[test]
fn ip_correct() {
    let ip = super::ip("8.8.8.8:80");
    let correct = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(8, 8, 8, 8), 80));
    assert_eq!(ip, correct);
}

#[test]
#[should_panic(expected = "because localhost can resolve to both 127.0.0.1, and the various IPV6 versions \
        of 127.0.0.1, it may not be used. please instead use 127.0.0.1")]
fn ip_localhost() {
    super::ip("localhost:80");
}
<commit_msg>Start logging in the ip family of tests<commit_after>use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
use std::sync::{Arc, Mutex, RwLock};
use std::sync::mpsc::{channel, Sender};
use std::time::Duration;
use std::thread;

use ::test_util::{TEST_SLEEP_TIME_MILLIS, start_log_once, Tattle};

#[test]
fn check_controller_channel_runs() {
    start_log_once();
    let (tx, rx): (Sender<super::ControllerMessage>, _) = channel();
    let controller_raw = Arc::new(super::ControllerRaw {
        connections: RwLock::new(Vec::new()),
        tx: Mutex::new(tx),
    });
    let controller_raw_clone = controller_raw.clone();
    thread::spawn(move || super::check_controller_channel(rx, controller_raw_clone));
    let tattle = Tattle::new();
    tattle.assert_changed(|| {
        controller_raw.tx.lock().unwrap().send(super::ControllerMessage::Test(tattle.clone())).unwrap();
        thread::sleep(Duration::from_millis(TEST_SLEEP_TIME_MILLIS));
    });
}

#[test]
fn ip_correct() {
    start_log_once();
    let ip = super::ip("8.8.8.8:80");
    let correct = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(8, 8, 8, 8), 80));
    assert_eq!(ip, correct);
}

#[test]
#[should_panic(expected = "because localhost can resolve to both 127.0.0.1, and the various IPV6 versions \
        of 127.0.0.1, it may not be used. please instead use 127.0.0.1")]
fn ip_localhost() {
    start_log_once();
    super::ip("localhost:80");
}
<|endoftext|>


<commit_before>use crate::utils::{
    match_def_path, match_type, method_calls, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty,
};
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::def::{DefKind, Res};
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::hir::*;
use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
use syntax::ast::{Crate as AstCrate, ItemKind, Name};
use syntax::source_map::Span;
use syntax_pos::symbol::LocalInternedString;

declare_clippy_lint! {
    /// **What it does:** Checks for various things we like to keep tidy in clippy.
    ///
    /// **Why is this bad?** We like to pretend we're an example of tidy code.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:** Wrong ordering of the util::paths constants.
    pub CLIPPY_LINTS_INTERNAL,
    internal,
    "various things that will negatively affect your clippy experience"
}

declare_clippy_lint! {
    /// **What it does:** Ensures every lint is associated to a `LintPass`.
    ///
    /// **Why is this bad?** The compiler only knows lints via a `LintPass`. Without
    /// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not
    /// know the name of the lint.
    ///
    /// **Known problems:** Only checks for lints associated using the
    /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// declare_lint! { pub LINT_1, ... }
    /// declare_lint! { pub LINT_2, ... }
    /// declare_lint! { pub FORGOTTEN_LINT, ... }
    /// // ...
    /// declare_lint_pass!(Pass => [LINT_1, LINT_2]);
    /// // missing FORGOTTEN_LINT
    /// ```
    pub LINT_WITHOUT_LINT_PASS,
    internal,
    "declaring a lint without associating it in a LintPass"
}

declare_clippy_lint! {
    /// **What it does:** Checks for calls to `cx.span_lint*` and suggests to use the `utils::*`
    /// variant of the function.
    ///
    /// **Why is this bad?** The `utils::*` variants also add a link to the Clippy documentation to the
    /// warning/error messages.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// Bad:
    /// ```rust,ignore
    /// cx.span_lint(LINT_NAME, "message");
    /// ```
    ///
    /// Good:
    /// ```rust,ignore
    /// utils::span_lint(cx, LINT_NAME, "message");
    /// ```
    pub COMPILER_LINT_FUNCTIONS,
    internal,
    "usage of the lint functions of the compiler instead of the utils::* variant"
}

declare_clippy_lint! {
    /// **What it does:** Checks for calls to `cx.outer().expn_data()` and suggests to use
    /// the `cx.outer_expn_data()`
    ///
    /// **Why is this bad?** `cx.outer_expn_data()` is faster and more concise.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// Bad:
    /// ```rust,ignore
    /// expr.span.ctxt().outer().expn_data()
    /// ```
    ///
    /// Good:
    /// ```rust,ignore
    /// expr.span.ctxt().outer_expn_data()
    /// ```
    pub OUTER_EXPN_EXPN_DATA,
    internal,
    "using `cx.outer_expn().expn_data()` instead of `cx.outer_expn_data()`"
}

declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);

impl EarlyLintPass for ClippyLintsInternal {
    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) {
        if let Some(utils) = krate
            .module
            .items
            .iter()
            .find(|item| item.ident.name.as_str() == "utils")
        {
            if let ItemKind::Mod(ref utils_mod) = utils.node {
                if let Some(paths) = utils_mod.items.iter().find(|item| item.ident.name.as_str() == "paths") {
                    if let ItemKind::Mod(ref paths_mod) = paths.node {
                        let mut last_name: Option<LocalInternedString> = None;
                        for item in &*paths_mod.items {
                            let name = item.ident.as_str();
                            if let Some(ref last_name) = last_name {
                                if **last_name > *name {
                                    span_lint(
                                        cx,
                                        CLIPPY_LINTS_INTERNAL,
                                        item.span,
                                        "this constant should be before the previous constant due to lexical \
                                         ordering",
                                    );
                                }
                            }
                            last_name = Some(name);
                        }
                    }
                }
            }
        }
    }
}

#[derive(Clone, Debug, Default)]
pub struct LintWithoutLintPass {
    declared_lints: FxHashMap<Name, Span>,
    registered_lints: FxHashSet<Name>,
}

impl_lint_pass!(LintWithoutLintPass => [LINT_WITHOUT_LINT_PASS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if let hir::ItemKind::Static(ref ty, MutImmutable, _) = item.node {
            if is_lint_ref_type(cx, ty) {
                self.declared_lints.insert(item.ident.name, item.span);
            }
        } else if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node {
            if_chain! {
                if let hir::TraitRef{path, ..} = trait_ref;
                if let Res::Def(DefKind::Trait, def_id) = path.res;
                if match_def_path(cx, def_id, &paths::LINT_PASS);
                then {
                    let mut collector = LintCollector {
                        output: &mut self.registered_lints,
                        cx,
                    };
                    let body_id = cx.tcx.hir().body_owned_by(
                        impl_item_refs
                            .iter()
                            .find(|iiref| iiref.ident.as_str() == "get_lints")
                            .expect("LintPass needs to implement get_lints")
                            .id.hir_id
                    );
                    collector.visit_expr(&cx.tcx.hir().body(body_id).value);
                }
            }
        }
    }

    fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, _: &'tcx Crate) {
        for (lint_name, &lint_span) in &self.declared_lints {
            // When using the `declare_tool_lint!` macro, the original `lint_span`'s
            // file points to "<rustc macros>".
            // `compiletest-rs` thinks that's an error in a different file and
            // just ignores it. This causes the test in compile-fail/lint_pass
            // not able to capture the error.
            // Therefore, we need to climb the macro expansion tree and find the
            // actual span that invoked `declare_tool_lint!`:
            let lint_span = lint_span
                .ctxt()
                .outer_expn_data()
                .call_site;

            if !self.registered_lints.contains(lint_name) {
                span_lint(
                    cx,
                    LINT_WITHOUT_LINT_PASS,
                    lint_span,
                    &format!("the lint `{}` is not added to any `LintPass`", lint_name),
                );
            }
        }
    }
}

fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool {
    if let TyKind::Rptr(
        _,
        MutTy {
            ty: ref inner,
            mutbl: MutImmutable,
        },
    ) = ty.node
    {
        if let TyKind::Path(ref path) = inner.node {
            if let Res::Def(DefKind::Struct, def_id) = cx.tables.qpath_res(path, inner.hir_id) {
                return match_def_path(cx, def_id, &paths::LINT);
            }
        }
    }

    false
}

struct LintCollector<'a, 'tcx> {
    output: &'a mut FxHashSet<Name>,
    cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'tcx Expr) {
        walk_expr(self, expr);
    }

    fn visit_path(&mut self, path: &'tcx Path, _: HirId) {
        if path.segments.len() == 1 {
            self.output.insert(path.segments[0].ident.name);
        }
    }
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::All(&self.cx.tcx.hir())
    }
}

#[derive(Clone, Default)]
pub struct CompilerLintFunctions {
    map: FxHashMap<&'static str, &'static str>,
}

impl CompilerLintFunctions {
    pub fn new() -> Self {
        let mut map = FxHashMap::default();
        map.insert("span_lint", "utils::span_lint");
        map.insert("struct_span_lint", "utils::span_lint");
        map.insert("lint", "utils::span_lint");
        map.insert("span_lint_note", "utils::span_note_and_lint");
        map.insert("span_lint_help", "utils::span_help_and_lint");
        Self { map }
    }
}

impl_lint_pass!(CompilerLintFunctions => [COMPILER_LINT_FUNCTIONS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if_chain! {
            if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
            let fn_name = path.ident;
            if let Some(sugg) = self.map.get(&*fn_name.as_str());
            let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
            if match_type(cx, ty, &paths::EARLY_CONTEXT)
                || match_type(cx, ty, &paths::LATE_CONTEXT);
            then {
                span_help_and_lint(
                    cx,
                    COMPILER_LINT_FUNCTIONS,
                    path.ident.span,
                    "usage of a compiler lint function",
                    &format!("please use the Clippy variant of this function: `{}`", sugg),
                );
            }
        }
    }
}

pub struct OuterExpnDataPass;

impl_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnDataPass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        let (method_names, arg_lists) = method_calls(expr, 2);
        let method_names: Vec<LocalInternedString> = method_names.iter().map(|s| s.as_str()).collect();
        let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect();
        if_chain! {
            if let ["expn_data", "outer_expn"] = method_names.as_slice();
            let args = arg_lists[1];
            if args.len() == 1;
            let self_arg = &args[0];
            let self_ty = walk_ptrs_ty(cx.tables.expr_ty(self_arg));
            if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
            then {
                span_lint_and_sugg(
                    cx,
                    OUTER_EXPN_EXPN_DATA,
                    expr.span.trim_start(self_arg.span).unwrap_or(expr.span),
                    "usage of `outer_expn().expn_data()`",
                    "try",
                    ".outer_expn_data()".to_string(),
                    Applicability::MachineApplicable,
                );
            }
        }
    }
}
<commit_msg>Run rustfmt<commit_after>use crate::utils::{
    match_def_path, match_type, method_calls, paths, span_help_and_lint, span_lint, span_lint_and_sugg, walk_ptrs_ty,
};
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::def::{DefKind, Res};
use rustc::hir::intravisit::{walk_expr, NestedVisitorMap, Visitor};
use rustc::hir::*;
use rustc::lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintPass};
use rustc::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
use syntax::ast::{Crate as AstCrate, ItemKind, Name};
use syntax::source_map::Span;
use syntax_pos::symbol::LocalInternedString;

declare_clippy_lint! {
    /// **What it does:** Checks for various things we like to keep tidy in clippy.
    ///
    /// **Why is this bad?** We like to pretend we're an example of tidy code.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:** Wrong ordering of the util::paths constants.
    pub CLIPPY_LINTS_INTERNAL,
    internal,
    "various things that will negatively affect your clippy experience"
}

declare_clippy_lint! {
    /// **What it does:** Ensures every lint is associated to a `LintPass`.
    ///
    /// **Why is this bad?** The compiler only knows lints via a `LintPass`. Without
    /// putting a lint to a `LintPass::get_lints()`'s return, the compiler will not
    /// know the name of the lint.
    ///
    /// **Known problems:** Only checks for lints associated using the
    /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros.
    ///
    /// **Example:**
    /// ```rust,ignore
    /// declare_lint! { pub LINT_1, ... }
    /// declare_lint! { pub LINT_2, ... }
    /// declare_lint! { pub FORGOTTEN_LINT, ... }
    /// // ...
    /// declare_lint_pass!(Pass => [LINT_1, LINT_2]);
    /// // missing FORGOTTEN_LINT
    /// ```
    pub LINT_WITHOUT_LINT_PASS,
    internal,
    "declaring a lint without associating it in a LintPass"
}

declare_clippy_lint! {
    /// **What it does:** Checks for calls to `cx.span_lint*` and suggests to use the `utils::*`
    /// variant of the function.
    ///
    /// **Why is this bad?** The `utils::*` variants also add a link to the Clippy documentation to the
    /// warning/error messages.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// Bad:
    /// ```rust,ignore
    /// cx.span_lint(LINT_NAME, "message");
    /// ```
    ///
    /// Good:
    /// ```rust,ignore
    /// utils::span_lint(cx, LINT_NAME, "message");
    /// ```
    pub COMPILER_LINT_FUNCTIONS,
    internal,
    "usage of the lint functions of the compiler instead of the utils::* variant"
}

declare_clippy_lint! {
    /// **What it does:** Checks for calls to `cx.outer().expn_data()` and suggests to use
    /// the `cx.outer_expn_data()`
    ///
    /// **Why is this bad?** `cx.outer_expn_data()` is faster and more concise.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// Bad:
    /// ```rust,ignore
    /// expr.span.ctxt().outer().expn_data()
    /// ```
    ///
    /// Good:
    /// ```rust,ignore
    /// expr.span.ctxt().outer_expn_data()
    /// ```
    pub OUTER_EXPN_EXPN_DATA,
    internal,
    "using `cx.outer_expn().expn_data()` instead of `cx.outer_expn_data()`"
}

declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]);

impl EarlyLintPass for ClippyLintsInternal {
    fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &AstCrate) {
        if let Some(utils) = krate
            .module
            .items
            .iter()
            .find(|item| item.ident.name.as_str() == "utils")
        {
            if let ItemKind::Mod(ref utils_mod) = utils.node {
                if let Some(paths) = utils_mod.items.iter().find(|item| item.ident.name.as_str() == "paths") {
                    if let ItemKind::Mod(ref paths_mod) = paths.node {
                        let mut last_name: Option<LocalInternedString> = None;
                        for item in &*paths_mod.items {
                            let name = item.ident.as_str();
                            if let Some(ref last_name) = last_name {
                                if **last_name > *name {
                                    span_lint(
                                        cx,
                                        CLIPPY_LINTS_INTERNAL,
                                        item.span,
                                        "this constant should be before the previous constant due to lexical \
                                         ordering",
                                    );
                                }
                            }
                            last_name = Some(name);
                        }
                    }
                }
            }
        }
    }
}

#[derive(Clone, Debug, Default)]
pub struct LintWithoutLintPass {
    declared_lints: FxHashMap<Name, Span>,
    registered_lints: FxHashSet<Name>,
}

impl_lint_pass!(LintWithoutLintPass => [LINT_WITHOUT_LINT_PASS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LintWithoutLintPass {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) {
        if let hir::ItemKind::Static(ref ty, MutImmutable, _) = item.node {
            if is_lint_ref_type(cx, ty) {
                self.declared_lints.insert(item.ident.name, item.span);
            }
        } else if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node {
            if_chain! {
                if let hir::TraitRef{path, ..} = trait_ref;
                if let Res::Def(DefKind::Trait, def_id) = path.res;
                if match_def_path(cx, def_id, &paths::LINT_PASS);
                then {
                    let mut collector = LintCollector {
                        output: &mut self.registered_lints,
                        cx,
                    };
                    let body_id = cx.tcx.hir().body_owned_by(
                        impl_item_refs
                            .iter()
                            .find(|iiref| iiref.ident.as_str() == "get_lints")
                            .expect("LintPass needs to implement get_lints")
                            .id.hir_id
                    );
                    collector.visit_expr(&cx.tcx.hir().body(body_id).value);
                }
            }
        }
    }

    fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, _: &'tcx Crate) {
        for (lint_name, &lint_span) in &self.declared_lints {
            // When using the `declare_tool_lint!` macro, the original `lint_span`'s
            // file points to "<rustc macros>".
            // `compiletest-rs` thinks that's an error in a different file and
            // just ignores it. This causes the test in compile-fail/lint_pass
            // not able to capture the error.
            // Therefore, we need to climb the macro expansion tree and find the
            // actual span that invoked `declare_tool_lint!`:
            let lint_span = lint_span.ctxt().outer_expn_data().call_site;

            if !self.registered_lints.contains(lint_name) {
                span_lint(
                    cx,
                    LINT_WITHOUT_LINT_PASS,
                    lint_span,
                    &format!("the lint `{}` is not added to any `LintPass`", lint_name),
                );
            }
        }
    }
}

fn is_lint_ref_type<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &Ty) -> bool {
    if let TyKind::Rptr(
        _,
        MutTy {
            ty: ref inner,
            mutbl: MutImmutable,
        },
    ) = ty.node
    {
        if let TyKind::Path(ref path) = inner.node {
            if let Res::Def(DefKind::Struct, def_id) = cx.tables.qpath_res(path, inner.hir_id) {
                return match_def_path(cx, def_id, &paths::LINT);
            }
        }
    }

    false
}

struct LintCollector<'a, 'tcx> {
    output: &'a mut FxHashSet<Name>,
    cx: &'a LateContext<'a, 'tcx>,
}

impl<'a, 'tcx> Visitor<'tcx> for LintCollector<'a, 'tcx> {
    fn visit_expr(&mut self, expr: &'tcx Expr) {
        walk_expr(self, expr);
    }

    fn visit_path(&mut self, path: &'tcx Path, _: HirId) {
        if path.segments.len() == 1 {
            self.output.insert(path.segments[0].ident.name);
        }
    }
    fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> {
        NestedVisitorMap::All(&self.cx.tcx.hir())
    }
}

#[derive(Clone, Default)]
pub struct CompilerLintFunctions {
    map: FxHashMap<&'static str, &'static str>,
}

impl CompilerLintFunctions {
    pub fn new() -> Self {
        let mut map = FxHashMap::default();
        map.insert("span_lint", "utils::span_lint");
        map.insert("struct_span_lint", "utils::span_lint");
        map.insert("lint", "utils::span_lint");
        map.insert("span_lint_note", "utils::span_note_and_lint");
        map.insert("span_lint_help", "utils::span_help_and_lint");
        Self { map }
    }
}

impl_lint_pass!(CompilerLintFunctions => [COMPILER_LINT_FUNCTIONS]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if_chain! {
            if let ExprKind::MethodCall(ref path, _, ref args) = expr.node;
            let fn_name = path.ident;
            if let Some(sugg) = self.map.get(&*fn_name.as_str());
            let ty = walk_ptrs_ty(cx.tables.expr_ty(&args[0]));
            if match_type(cx, ty, &paths::EARLY_CONTEXT)
                || match_type(cx, ty, &paths::LATE_CONTEXT);
            then {
                span_help_and_lint(
                    cx,
                    COMPILER_LINT_FUNCTIONS,
                    path.ident.span,
                    "usage of a compiler lint function",
                    &format!("please use the Clippy variant of this function: `{}`", sugg),
                );
            }
        }
    }
}

pub struct OuterExpnDataPass;

impl_lint_pass!(OuterExpnDataPass => [OUTER_EXPN_EXPN_DATA]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnDataPass {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        let (method_names, arg_lists) = method_calls(expr, 2);
        let method_names: Vec<LocalInternedString> = method_names.iter().map(|s| s.as_str()).collect();
        let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect();
        if_chain! {
            if let ["expn_data", "outer_expn"] = method_names.as_slice();
            let args = arg_lists[1];
            if args.len() == 1;
            let self_arg = &args[0];
            let self_ty = walk_ptrs_ty(cx.tables.expr_ty(self_arg));
            if match_type(cx, self_ty, &paths::SYNTAX_CONTEXT);
            then {
                span_lint_and_sugg(
                    cx,
                    OUTER_EXPN_EXPN_DATA,
                    expr.span.trim_start(self_arg.span).unwrap_or(expr.span),
                    "usage of `outer_expn().expn_data()`",
                    "try",
                    ".outer_expn_data()".to_string(),
                    Applicability::MachineApplicable,
                );
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015 William (B.J.) Snow Orvis
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Computations and abstractions needed for rendering a terdragon fractal.

use common::{Point, Turtle};

const SQRT_3: f64 = 1.7320508075;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum Turn {
    Left,
    Right,
}

#[derive(Copy, Clone, Debug)]
pub struct TerdragonFractal {
    iterations: u64,
}

/// Represents the computations needed to render a terdragon fractal of a particular iteration. It
/// uses a Lindenmeyer system under the hood
impl TerdragonFractal {
    /// Create a new TerdragonFractal. `iterations` is the number of generations to apply to the
    /// Lindenmeyer system used to generate the fractal's turns.
    /// ```
    pub fn new(iterations: u64) -> Result<TerdragonFractal, &'static str> {
        let df = TerdragonFractal { iterations: iterations };
        Ok(df)
    }

    /// The number of lines that will be drawn.
    ///
    /// Essentially: 3^(iterations)
    pub fn number_of_steps(self) -> u64 {
        (3 as u64).pow((self.iterations) as u32)
    }

    /// How many line segments are between the starting and end points.
    ///
    /// This can be used to calculate how long each line segment should be to ensure that the
    /// drawing of the fractal ends at the desired endpoints. For example, if the starting point is
    /// (0, 0) and the endpoint should be (1, 0), then the size of each line segment would be:
    ///
    ///     (x_start - x_end).abs() / df.lines_between_endpoints()
    ///
    pub fn lines_between_endpoints(self) -> f64 {
        match self.iterations {
            0 => 1.0,
            _ => SQRT_3.powf(self.iterations as f64),
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LSA {
    F,
    L,
    R,
}

use lindenmayer::{LindenmayerSystem, LindenmayerSystemDrawingParameters};

impl LindenmayerSystem<LSA> for TerdragonFractal {
    fn initial() -> Vec<LSA> {
        vec![LSA::F]
    }

    fn apply_rule(lstr: LSA) -> Vec<LSA> {
        match lstr {
            LSA::F => vec![LSA::F, LSA::L, LSA::F, LSA::R, LSA::F],
            x => vec![x],
        }
    }
}

impl LindenmayerSystemDrawingParameters<LSA> for TerdragonFractal {
    fn iteration(&self) -> u64 {
        self.iterations
    }
    fn initialize_turtle(&self, turtle: &mut Turtle) {
        use std::f64::consts::PI;
        turtle.set_pos(Point { x: 0.0, y: 0.0 });
        turtle.set_rad(PI / 6.0 * -(self.iterations as f64));
    }

    fn interpret_symbol(&self, symbol: LSA, turtle: &mut Turtle) {
        match symbol {
            LSA::F => turtle.forward(1.0 / (self.lines_between_endpoints() as f64)),
            LSA::L => turtle.turn_deg(120.0),
            LSA::R => turtle.turn_deg(-120.0),
        }
    }
}

#[cfg(test)]
mod test {
    use super::SQRT_3;
    use super::{LSA, TerdragonFractal};

    #[test]
    fn test_step_count() {
        assert_eq!(TerdragonFractal::new(0).unwrap().number_of_steps(), 1);
        assert_eq!(TerdragonFractal::new(1).unwrap().number_of_steps(), 3);
        assert_eq!(TerdragonFractal::new(2).unwrap().number_of_steps(), 9);
        assert_eq!(TerdragonFractal::new(3).unwrap().number_of_steps(), 27);
    }

    #[test]
    fn test_lines_between_endpoints() {
        assert_approx_eq!(TerdragonFractal::new(0).unwrap().lines_between_endpoints(),
                          1.0,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(1).unwrap().lines_between_endpoints(),
                          SQRT_3,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(2).unwrap().lines_between_endpoints(),
                          3.0,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(3).unwrap().lines_between_endpoints(),
                          3.0 * SQRT_3,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(4).unwrap().lines_between_endpoints(),
                          9.0,
                          0.000001);
    }

    #[test]
    fn test_l_system() {
        use super::super::lindenmayer::LindenmayerSystem; // needed to pull in generate()
        assert_eq!(TerdragonFractal::generate(0), [LSA::F]);
        assert_eq!(TerdragonFractal::generate(1),
                   [LSA::F, LSA::L, LSA::F, LSA::R, LSA::F]);
        assert_eq!(TerdragonFractal::generate(2),
                   [LSA::F, LSA::L, LSA::F, LSA::R, LSA::F, LSA::L, LSA::F, LSA::L, LSA::F,
                    LSA::R, LSA::F, LSA::R, LSA::F, LSA::L, LSA::F, LSA::R, LSA::F]);
    }
}
<commit_msg>Some terdragon cleanup<commit_after>// Copyright (c) 2015 William (B.J.) Snow Orvis
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Computations and abstractions needed for rendering a terdragon fractal.

use common::{Point, Turtle};
use lindenmayer::{LindenmayerSystem, LindenmayerSystemDrawingParameters};

const SQRT_3: f64 = 1.7320508075;

#[derive(Copy, Clone, Debug)]
pub struct TerdragonFractal {
    iterations: u64,
}

/// Represents the computations needed to render a terdragon fractal of a particular iteration. It
/// uses a Lindenmeyer system under the hood
impl TerdragonFractal {
    /// Create a new TerdragonFractal. `iterations` is the number of generations to apply to the
    /// Lindenmeyer system used to generate the fractal's turns.
    /// ```
    pub fn new(iterations: u64) -> Result<TerdragonFractal, &'static str> {
        let df = TerdragonFractal { iterations: iterations };
        Ok(df)
    }

    /// The number of lines that will be drawn.
    ///
    /// Essentially: 3^(iterations)
    pub fn number_of_steps(self) -> u64 {
        (3 as u64).pow((self.iterations) as u32)
    }

    /// How many line segments are between the starting and end points.
    ///
    /// This can be used to calculate how long each line segment should be to ensure that the
    /// drawing of the fractal ends at the desired endpoints. For example, if the starting point is
    /// (0, 0) and the endpoint should be (1, 0), then the size of each line segment would be:
    ///
    ///     (x_start - x_end).abs() / df.lines_between_endpoints()
    ///
    pub fn lines_between_endpoints(self) -> f64 {
        match self.iterations {
            0 => 1.0,
            _ => SQRT_3.powf(self.iterations as f64),
        }
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum LSA {
    F,
    L,
    R,
}

impl LindenmayerSystem<LSA> for TerdragonFractal {
    fn initial() -> Vec<LSA> {
        vec![LSA::F]
    }

    fn apply_rule(lstr: LSA) -> Vec<LSA> {
        match lstr {
            LSA::F => vec![LSA::F, LSA::L, LSA::F, LSA::R, LSA::F],
            x => vec![x],
        }
    }
}

impl LindenmayerSystemDrawingParameters<LSA> for TerdragonFractal {
    fn iteration(&self) -> u64 {
        self.iterations
    }
    fn initialize_turtle(&self, turtle: &mut Turtle) {
        use std::f64::consts::PI;
        turtle.set_pos(Point { x: 0.0, y: 0.0 });
        turtle.set_rad(PI / 6.0 * -(self.iterations as f64));
    }

    fn interpret_symbol(&self, symbol: LSA, turtle: &mut Turtle) {
        match symbol {
            LSA::F => turtle.forward(1.0 / (self.lines_between_endpoints() as f64)),
            LSA::L => turtle.turn_deg(120.0),
            LSA::R => turtle.turn_deg(-120.0),
        }
    }
}

#[cfg(test)]
mod test {
    use super::SQRT_3;
    use super::{LSA, TerdragonFractal};

    #[test]
    fn test_step_count() {
        assert_eq!(TerdragonFractal::new(0).unwrap().number_of_steps(), 1);
        assert_eq!(TerdragonFractal::new(1).unwrap().number_of_steps(), 3);
        assert_eq!(TerdragonFractal::new(2).unwrap().number_of_steps(), 9);
        assert_eq!(TerdragonFractal::new(3).unwrap().number_of_steps(), 27);
    }

    #[test]
    fn test_lines_between_endpoints() {
        assert_approx_eq!(TerdragonFractal::new(0).unwrap().lines_between_endpoints(),
                          1.0,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(1).unwrap().lines_between_endpoints(),
                          SQRT_3,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(2).unwrap().lines_between_endpoints(),
                          3.0,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(3).unwrap().lines_between_endpoints(),
                          3.0 * SQRT_3,
                          0.000001);
        assert_approx_eq!(TerdragonFractal::new(4).unwrap().lines_between_endpoints(),
                          9.0,
                          0.000001);
    }

    #[test]
    fn test_l_system() {
        use super::super::lindenmayer::LindenmayerSystem; // needed to pull in generate()
        assert_eq!(TerdragonFractal::generate(0), [LSA::F]);
        assert_eq!(TerdragonFractal::generate(1),
                   [LSA::F, LSA::L, LSA::F, LSA::R, LSA::F]);
        assert_eq!(TerdragonFractal::generate(2),
                   [LSA::F, LSA::L, LSA::F, LSA::R, LSA::F, LSA::L, LSA::F, LSA::L, LSA::F,
                    LSA::R, LSA::F, LSA::R, LSA::F, LSA::L, LSA::F, LSA::R, LSA::F]);
    }
}
<|endoftext|>


<commit_before>#![allow(dead_code)]
use std::fmt;
use std::rc::{Rc, Weak};
use entity::{Vec3f64, Entity};

struct Address {
    x: u64,
    y: u64,
    z: u64,
}

struct Element {
    name: String,
}

pub enum ChunkOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>)
}

pub enum ChildOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub enum ParentOption {
    Local(Weak<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub struct LocalChunk {
    address: Address,
    center: Vec3f64,
    //children: [ChildOption; 8],
    //FIXME: remove these and uncomment above
    child0: ChildOption,
    child1: ChildOption,
    child2: ChildOption,
    child3: ChildOption,
    child4: ChildOption,
    child5: ChildOption,
    child6: ChildOption,
    child7: ChildOption,
    //END FIXME
    child_number: Option<u8>,
    entities: Vec<Rc<Entity>>,
    mass: f64,
    parent: ParentOption,
    scale: u8,
    structure: u64,
    summary: Rc<Element>,
}

pub struct RemoteChunk {
    connection: i32,
}

impl Address {
    fn from_string(address: String) -> Option<Address> {
        let mut xyz: (u64, u64, u64) = (1, 1, 1);
        let mut xyz_add: (u64, u64, u64);

        for (i, c) in address.chars().enumerate() {
            if i > 63 {
                break;
            }
            xyz_add =  match c.to_digit(8) {
                Some(0) => (0, 0, 0),
                Some(1) => (0, 0, 1),
                Some(2) => (0, 1, 0),
                Some(3) => (0, 1, 1),
                Some(4) => (1, 0, 0),
                Some(5) => (1, 0, 1),
                Some(6) => (1, 1, 0),
                Some(7) => (1, 1, 1),
                _ => return None,
            };
            xyz = (xyz.0 << 1, xyz.1 << 1, xyz.2 << 1);
            xyz = (xyz.0 + xyz_add.0, xyz.1 + xyz_add.1, xyz.2 + xyz_add.2);
        }
        Some(Address {x: xyz.0, y: xyz.1, z: xyz.2})
    }
}

impl ToString for Address {
    fn to_string(&self) -> String {
        String::from_str("")
    }
}

impl PartialEq for Address {
    fn eq(&self, other: &Self) -> bool {
        (((self.x == other.x) && (self.y == other.y)) && (self.z == other.z))
    }
}

impl fmt::Show for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Address({}, {}, {})", self.x, self.y, self.z)
    }
}

pub trait Chunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption;
    fn tick(&self, time_delta: f64);
}

impl Chunk for LocalChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {
        let index = match (x, y, z) {
            (0, 0, 0) => Some(0),
            (0, 0, 1) => Some(1),
            (0, 1, 0) => Some(2),
            (0, 1, 1) => Some(3),
            (1, 0, 0) => Some(4),
            (1, 0, 1) => Some(5),
            (1, 1, 0) => Some(6),
            (1, 1, 1) => Some(7),
            _ => None,
        };

        /* FIXME: remove
        if index == None {
            return ChildOption::None
        }

        match self.children[index] {
            ChildOption::Local(ref chunk) => ChildOption::Local(*chunk),
            ChildOption::Remote(ref chunk) => ChildOption::Remote(*chunk),
            ChildOption::None => ChildOption::None
        }*/
        //SLOP
        let child = match index {
            Some(0) => self.child0,
            Some(1) => self.child1,
            Some(2) => self.child2,
            Some(3) => self.child3,
            Some(4) => self.child4,
            Some(5) => self.child5,
            Some(6) => self.child6,
            Some(7) => self.child7,
            _ => return None
        };
        match child {
            ChildOption::Local(ref chunk) => ChildOption::Local(*chunk),
            ChildOption::Remote(ref chunk) => ChildOption::Remote(*chunk),
            ChildOption::None => ChildOption::None
        }
        //ENDSLOP
    }

    fn tick(&self, time_delta: f64) {
    }
}

impl Chunk for RemoteChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {
        ChildOption::None
    }
    fn tick (&self, time_delta: f64) {
    }
}

#[test]
fn test_address_from_string() {
    let known = Option::Some(Address {x: 0b11, y: 0b11, z: 0b11});
    let unknown = Address::from_string(String::from_str("7"));
    assert_eq!(known, unknown)
}
<commit_msg>IDK, sloppin<commit_after>#![allow(dead_code)]
use std::fmt;
use std::rc::{Rc, Weak};
use entity::{Vec3f64, Entity};

struct Address {
    x: u64,
    y: u64,
    z: u64,
}

struct Element {
    name: String,
}

pub enum ChunkOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>)
}

pub enum ChildOption {
    Local(Rc<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub enum ParentOption {
    Local(Weak<LocalChunk>),
    Remote(Rc<RemoteChunk>),
    None
}

pub struct LocalChunk {
    address: Address,
    center: Vec3f64,
    //children: [ChildOption; 8],
    //FIXME: remove these and uncomment above
    child0: ChildOption,
    child1: ChildOption,
    child2: ChildOption,
    child3: ChildOption,
    child4: ChildOption,
    child5: ChildOption,
    child6: ChildOption,
    child7: ChildOption,
    //END FIXME
    child_number: Option<u8>,
    entities: Vec<Rc<Entity>>,
    mass: f64,
    parent: ParentOption,
    scale: u8,
    structure: u64,
    summary: Rc<Element>,
}

pub struct RemoteChunk {
    connection: i32,
}

impl Address {
    fn from_string(address: String) -> Option<Address> {
        let mut xyz: (u64, u64, u64) = (1, 1, 1);
        let mut xyz_add: (u64, u64, u64);

        for (i, c) in address.chars().enumerate() {
            if i > 63 {
                break;
            }
            xyz_add =  match c.to_digit(8) {
                Some(0) => (0, 0, 0),
                Some(1) => (0, 0, 1),
                Some(2) => (0, 1, 0),
                Some(3) => (0, 1, 1),
                Some(4) => (1, 0, 0),
                Some(5) => (1, 0, 1),
                Some(6) => (1, 1, 0),
                Some(7) => (1, 1, 1),
                _ => return None,
            };
            xyz = (xyz.0 << 1, xyz.1 << 1, xyz.2 << 1);
            xyz = (xyz.0 + xyz_add.0, xyz.1 + xyz_add.1, xyz.2 + xyz_add.2);
        }
        Some(Address {x: xyz.0, y: xyz.1, z: xyz.2})
    }
}

impl ToString for Address {
    fn to_string(&self) -> String {
        String::from_str("")
    }
}

impl PartialEq for Address {
    fn eq(&self, other: &Self) -> bool {
        (((self.x == other.x) && (self.y == other.y)) && (self.z == other.z))
    }
}

impl fmt::Show for Address {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Address({}, {}, {})", self.x, self.y, self.z)
    }
}

pub trait Chunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption;
    fn tick(&self, time_delta: f64);
}

impl Chunk for LocalChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {

        /* FIXME: remove
        let index = match (x, y, z) {
            (0, 0, 0) => Some(0),
            (0, 0, 1) => Some(1),
            (0, 1, 0) => Some(2),
            (0, 1, 1) => Some(3),
            (1, 0, 0) => Some(4),
            (1, 0, 1) => Some(5),
            (1, 1, 0) => Some(6),
            (1, 1, 1) => Some(7),
            _ => None,
        };

        if index == None {
            return ChildOption::None
        }

        match self.children[index] {
            ChildOption::Local(ref chunk) => ChildOption::Local(*chunk),
            ChildOption::Remote(ref chunk) => ChildOption::Remote(*chunk),
            ChildOption::None => ChildOption::None
        }*/
        //SLOP
        let child = match (x, y, z) {
            (0, 0, 0) => Some(self.child0),
            (0, 0, 1) => Some(self.child1),
            (0, 1, 0) => Some(self.child2),
            (0, 1, 1) => Some(self.child3),
            (1, 0, 0) => Some(self.child4),
            (1, 0, 1) => Some(self.child5),
            (1, 1, 0) => Some(self.child6),
            (1, 1, 1) => Some(self.child7),
            _ => None,
        };
        match child {
            Some(ChildOption::Local(ref chunk)) => ChildOption::Local(*chunk),
            Some(ChildOption::Remote(ref chunk)) => ChildOption::Remote(*chunk),
            _ => ChildOption::None
        }
        //ENDSLOP
    }

    fn tick(&self, time_delta: f64) {
    }
}

impl Chunk for RemoteChunk {
    fn get_child(&self, x: u8, y: u8, z: u8) -> ChildOption {
        ChildOption::None
    }
    fn tick (&self, time_delta: f64) {
    }
}

#[test]
fn test_address_from_string() {
    let known = Option::Some(Address {x: 0b11, y: 0b11, z: 0b11});
    let unknown = Address::from_string(String::from_str("7"));
    assert_eq!(known, unknown)
}
<|endoftext|>


<commit_before>use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::TyKind;

use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg};

/// **What it does:** Checks for literal calls to `Default::default()`.
///
/// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
/// being gotten than the generic `Default`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// // Bad
/// let s: String = Default::default();
///
/// // Good
/// let s = String::default();
/// ```
declare_clippy_lint! {
    pub DEFAULT_TRAIT_ACCESS,
    pedantic,
    "checks for literal calls to Default::default()"
}

#[derive(Copy, Clone)]
pub struct DefaultTraitAccess;

impl LintPass for DefaultTraitAccess {
    fn get_lints(&self) -> LintArray {
        lint_array!(DEFAULT_TRAIT_ACCESS)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if_chain! {
            if let ExprKind::Call(ref path, ..) = expr.node;
            if !any_parent_is_automatically_derived(cx.tcx, expr.id);
            if let ExprKind::Path(ref qpath) = path.node;
            if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));
            if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD);
            then {
                match qpath {
                    QPath::Resolved(..) => {
                        if_chain! {
                            // Detect and ignore <Foo as Default>::default() because these calls do
                            // explicitly name the type.
                            if let ExprKind::Call(ref method, ref _args) = expr.node;
                            if let ExprKind::Path(ref p) = method.node;
                            if let QPath::Resolved(ref ty, ref _path) = p;
                            if ty.is_some();
                            then {
                                return;
                            }
                        }

                        // TODO: Work out a way to put "whatever the imported way of referencing
                        // this type in this file" rather than a fully-qualified type.
                        let expr_ty = cx.tables.expr_ty(expr);
                        if let TyKind::Adt(..) = expr_ty.sty {
                            let replacement = format!("{}::default()", expr_ty);
                            span_lint_and_sugg(
                                cx,
                                DEFAULT_TRAIT_ACCESS,
                                expr.span,
                                &format!("Calling {} is more clear than this expression", replacement),
                                "try",
                                replacement);
                         }
                    },
                    QPath::TypeRelative(..) => {},
                }
            }
         }
    }
}
<commit_msg>Simplify<commit_after>use rustc::hir::*;
use rustc::lint::*;
use rustc::{declare_lint, lint_array};
use if_chain::if_chain;
use rustc::ty::TyKind;

use crate::utils::{any_parent_is_automatically_derived, match_def_path, opt_def_id, paths, span_lint_and_sugg};

/// **What it does:** Checks for literal calls to `Default::default()`.
///
/// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
/// being gotten than the generic `Default`.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// // Bad
/// let s: String = Default::default();
///
/// // Good
/// let s = String::default();
/// ```
declare_clippy_lint! {
    pub DEFAULT_TRAIT_ACCESS,
    pedantic,
    "checks for literal calls to Default::default()"
}

#[derive(Copy, Clone)]
pub struct DefaultTraitAccess;

impl LintPass for DefaultTraitAccess {
    fn get_lints(&self) -> LintArray {
        lint_array!(DEFAULT_TRAIT_ACCESS)
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DefaultTraitAccess {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) {
        if_chain! {
            if let ExprKind::Call(ref path, ..) = expr.node;
            if !any_parent_is_automatically_derived(cx.tcx, expr.id);
            if let ExprKind::Path(ref qpath) = path.node;
            if let Some(def_id) = opt_def_id(cx.tables.qpath_def(qpath, path.hir_id));
            if match_def_path(cx.tcx, def_id, &paths::DEFAULT_TRAIT_METHOD);
            then {
                match qpath {
                    QPath::Resolved(..) => {
                        if_chain! {
                            // Detect and ignore <Foo as Default>::default() because these calls do
                            // explicitly name the type.
                            if let ExprKind::Call(ref method, ref _args) = expr.node;
                            if let ExprKind::Path(ref p) = method.node;
                            if let QPath::Resolved(Some(_ty), _path) = p;
                            then {
                                return;
                            }
                        }

                        // TODO: Work out a way to put "whatever the imported way of referencing
                        // this type in this file" rather than a fully-qualified type.
                        let expr_ty = cx.tables.expr_ty(expr);
                        if let TyKind::Adt(..) = expr_ty.sty {
                            let replacement = format!("{}::default()", expr_ty);
                            span_lint_and_sugg(
                                cx,
                                DEFAULT_TRAIT_ACCESS,
                                expr.span,
                                &format!("Calling {} is more clear than this expression", replacement),
                                "try",
                                replacement);
                         }
                    },
                    QPath::TypeRelative(..) => {},
                }
            }
         }
    }
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The GeoRust Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::iter::Peekable;

#[derive(PartialEq, Debug)]
pub enum Token {
    Comma,
    Number(f64),
    ParenClose,
    ParenOpen,
    Word(String),
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\n' | '\r' | '\t' | ' ' => true,
        _                        => false,
    }
}

fn is_numberlike(c: char) -> bool {
    match c {
        c if c.is_numeric() => true,
        '.' | '-' | '+'     => true,
        _                   => false,
    }
}

pub type PeekableTokens = Peekable<Token, Tokens>;

pub struct Tokens {
    text: String
}

impl Tokens {
    pub fn from_str(input: &str) -> Self {
        Tokens {text: String::from_str(input)}
    }
}

impl Iterator for Tokens {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {
        let next_char = match self.pop_front() {
            Some(c) => c,
            None => return None,
        };

        match next_char {
            '\0' => None,
            '(' => Some(Token::ParenOpen),
            ')' => Some(Token::ParenClose),
            ',' => Some(Token::Comma),
            c if is_whitespace(c) => self.next(),
            c if is_numberlike(c) => {
                let mut number = c.to_string() + &self.read_until_whitespace();
                number = number.trim_left_matches('+').to_string();
                match number.parse::<f64>() {
                    Ok(parsed_num) => Some(Token::Number(parsed_num)),
                    Err(e) => panic!("Could not parse number: {}", e),
                }
            }
            c => {
                let word = c.to_string() + &self.read_until_whitespace();
                Some(Token::Word(word))
            }
        }
    }
}

impl Tokens {
    fn pop_front(&mut self) -> Option<char> {
        match self.text.is_empty() {
            true => None,
            false => Some(self.text.remove(0))
        }
    }

    fn read_until_whitespace(&mut self) -> String {
        let next_char = match self.pop_front() {
            Some(c) => c,
            None => return "".to_string(),
        };

        match next_char {
            '\0' | '(' | ')' | ',' => {
                self.text.insert(0, next_char);
                "".to_string()
            }
            c if is_whitespace(c) => "".to_string(),
            _ => next_char.to_string() + &self.read_until_whitespace(),
        }
    }
}

#[test]
fn test_tokenizer_empty() {
    let test_str = "";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![]);
}

#[test]
fn test_tokenizer_1word() {
    let test_str = "hello";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
    ]);
}

#[test]
fn test_tokenizer_2words() {
    let test_str = "hello world";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
        Token::Word("world".to_string()),
    ]);
}

#[test]
fn test_tokenizer_1number() {
    let test_str = "4.2";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(4.2),
    ]);
}

#[test]
fn test_tokenizer_1number_plus() {
    let test_str = "+4.2";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(4.2),
    ]);
}

#[test]
fn test_tokenizer_2numbers() {
    let test_str = ".4 -2";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(0.4),
        Token::Number(-2.0),
    ]);
}

#[test]
fn test_tokenizer_point() {
    let test_str = "POINT (10 -20)";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("POINT".to_string()),
        Token::ParenOpen,
        Token::Number(10.0),
        Token::Number(-20.0),
        Token::ParenClose,
    ]);
}
<commit_msg>Add TODO<commit_after>// Copyright 2014-2015 The GeoRust Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::iter::Peekable;

#[derive(PartialEq, Debug)]
pub enum Token {
    Comma,
    Number(f64),
    ParenClose,
    ParenOpen,
    Word(String),
}

fn is_whitespace(c: char) -> bool {
    match c {
        '\n' | '\r' | '\t' | ' ' => true,
        _                        => false,
    }
}

fn is_numberlike(c: char) -> bool {
    match c {
        c if c.is_numeric() => true,
        '.' | '-' | '+'     => true,
        _                   => false,
    }
}

pub type PeekableTokens = Peekable<Token, Tokens>;

pub struct Tokens {
    text: String
}

impl Tokens {
    pub fn from_str(input: &str) -> Self {
        Tokens {text: String::from_str(input)}
    }
}

impl Iterator for Tokens {
    type Item = Token;

    fn next(&mut self) -> Option<Token> {  // TODO: should this return Result?
        let next_char = match self.pop_front() {
            Some(c) => c,
            None => return None,
        };

        match next_char {
            '\0' => None,
            '(' => Some(Token::ParenOpen),
            ')' => Some(Token::ParenClose),
            ',' => Some(Token::Comma),
            c if is_whitespace(c) => self.next(),
            c if is_numberlike(c) => {
                let mut number = c.to_string() + &self.read_until_whitespace();
                number = number.trim_left_matches('+').to_string();
                match number.parse::<f64>() {
                    Ok(parsed_num) => Some(Token::Number(parsed_num)),
                    Err(e) => panic!("Could not parse number: {}", e),
                }
            }
            c => {
                let word = c.to_string() + &self.read_until_whitespace();
                Some(Token::Word(word))
            }
        }
    }
}

impl Tokens {
    fn pop_front(&mut self) -> Option<char> {
        match self.text.is_empty() {
            true => None,
            false => Some(self.text.remove(0))
        }
    }

    fn read_until_whitespace(&mut self) -> String {
        let next_char = match self.pop_front() {
            Some(c) => c,
            None => return "".to_string(),
        };

        match next_char {
            '\0' | '(' | ')' | ',' => {
                self.text.insert(0, next_char);
                "".to_string()
            }
            c if is_whitespace(c) => "".to_string(),
            _ => next_char.to_string() + &self.read_until_whitespace(),
        }
    }
}

#[test]
fn test_tokenizer_empty() {
    let test_str = "";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![]);
}

#[test]
fn test_tokenizer_1word() {
    let test_str = "hello";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
    ]);
}

#[test]
fn test_tokenizer_2words() {
    let test_str = "hello world";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("hello".to_string()),
        Token::Word("world".to_string()),
    ]);
}

#[test]
fn test_tokenizer_1number() {
    let test_str = "4.2";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(4.2),
    ]);
}

#[test]
fn test_tokenizer_1number_plus() {
    let test_str = "+4.2";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(4.2),
    ]);
}

#[test]
fn test_tokenizer_2numbers() {
    let test_str = ".4 -2";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Number(0.4),
        Token::Number(-2.0),
    ]);
}

#[test]
fn test_tokenizer_point() {
    let test_str = "POINT (10 -20)";
    let tokens: Vec<Token> = Tokens::from_str(test_str).collect();
    assert_eq!(tokens, vec![
        Token::Word("POINT".to_string()),
        Token::ParenOpen,
        Token::Number(10.0),
        Token::Number(-20.0),
        Token::ParenClose,
    ]);
}
<|endoftext|>


<commit_before>
pub use self::manager::Manager;

/// The pass manager infrastructure.
pub mod manager;
/// Passes which perform transformations.
pub mod transforms;
/// Passes which perform analysis.
pub mod analysis;

use lang;

/// A pass identifier.
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub struct Id(u32);

pub enum Info<V: lang::Value>
{
    Analysis(Box<Analysis<V>>),
    Transform(Box<Transform<V>>),
}

impl<V: lang::Value> Metadata for Info<V>
{
    fn id(&self) -> Id {
        match *self {
            Info::Analysis(ref p) => p.id(),
            Info::Transform(ref p) => p.id(),
        }
    }

    fn dependencies(&self) -> &'static [Id] {
        match *self {
            Info::Analysis(ref p) => p.dependencies(),
            Info::Transform(ref p) => p.dependencies(),
        }
    }

    fn name(&self) -> &'static str {
        match *self {
            Info::Analysis(ref p) => p.name(),
            Info::Transform(ref p) => p.name(),
        }
    }
}

/// A pass over a set of instructions.
pub trait Metadata
{
    fn id(&self) -> Id;

    /// Gets the identifiers of the passes this pass
    /// depends on.
    fn dependencies(&self) -> &'static [Id] {
        &[]
    }

    fn name(&self) -> &'static str;
}

pub trait Analysis<V> : Metadata
    where V: lang::Value
{
    /// Run the pass on an entire module.
    fn run_module(&mut self, module: &lang::Module<V>) {

        for global in module.globals() {
            self.run_global(global);
        }

        for func in module.functions() {
            self.run_function(func);
        }
    }

    /// Run the pass on a global variable.
    fn run_global(&mut self, _: &lang::Global<V>) {
        // do nothing unless overidden
    }

    /// Run the pass on a function.
    fn run_function(&mut self, function: &lang::Function<V>) {

        for bb in function.blocks() {
            self.run_block(bb);
        }
    }

    /// Run the pass on a basic block.
    fn run_block(&mut self, block: &lang::Block<V>) {

        for value in block.values() {
            self.run_value_recursive(&value);
        }
    }

    /// Run the pass on a value.
    fn run_value(&mut self,
                 _: &V) {

        panic!("the pass is not implemented");
    }

    fn run_value_recursive(&mut self,
                           value: &V) {

        // Recurse from the deepest node to the root node.
        for val in value.subvalues() {
            self.run_value_recursive(&val);
        }

        self.run_value(value)
    }
}

pub trait Transform<V> : Metadata
    where V: lang::Value
{
    /// Run the pass on an entire module.
    fn run_module(&mut self, module: lang::Module<V>) -> lang::Module<V> {
        module.map_globals(|a| self.run_global(a))
              .map_functions(|a| self.run_function(a))
    }

    /// Run the pass on a global.
    fn run_global(&mut self, global: lang::Global<V>)
        -> lang::Global<V> {

        // do nothing unless overridden
        global
    }

    /// Run the pass on a function.
    fn run_function(&mut self, function: lang::Function<V>)
        -> lang::Function<V> {

        function.map_blocks(|a| self.run_block(a))
    }

    /// Run the pass on a basic block.
    fn run_block(&mut self, block: lang::Block<V>)
        -> lang::Block<V> {

        block.map_values(|a| self.run_value_recursive(a))
    }

    /// Run the pass on a value.
    fn run_value(&mut self,
                 _: V) -> V {

        panic!("the {} pass is not implemented", self.name());
    }

    fn run_value_recursive(&mut self,
                           value: V) -> V {

        // Recurse from the deepest node to the root node.
        let val = value.map_subvalues(|v| self.run_value_recursive(v));
        self.run_value(val)
    }
}

<commit_msg>Minor formatting nits<commit_after>
pub use self::manager::Manager;

/// The pass manager infrastructure.
pub mod manager;
/// Passes which perform transformations.
pub mod transforms;
/// Passes which perform analysis.
pub mod analysis;

use lang;

/// A pass identifier.
#[derive(Copy,Clone,Debug,PartialEq,Eq)]
pub struct Id(u32);

pub enum Info<V: lang::Value>
{
    Analysis(Box<Analysis<V>>),
    Transform(Box<Transform<V>>),
}

impl<V: lang::Value> Metadata for Info<V>
{
    fn id(&self) -> Id {
        match *self {
            Info::Analysis(ref p) => p.id(),
            Info::Transform(ref p) => p.id(),
        }
    }

    fn dependencies(&self) -> &'static [Id] {
        match *self {
            Info::Analysis(ref p) => p.dependencies(),
            Info::Transform(ref p) => p.dependencies(),
        }
    }

    fn name(&self) -> &'static str {
        match *self {
            Info::Analysis(ref p) => p.name(),
            Info::Transform(ref p) => p.name(),
        }
    }
}

/// A pass over a set of instructions.
pub trait Metadata
{
    fn id(&self) -> Id;

    /// Gets the identifiers of the passes this pass
    /// depends on.
    fn dependencies(&self) -> &'static [Id] {
        &[]
    }

    fn name(&self) -> &'static str;
}

pub trait Analysis<V> : Metadata
    where V: lang::Value
{
    /// Run the pass on an entire module.
    fn run_module(&mut self,
                  module: &lang::Module<V>) {

        for global in module.globals() {
            self.run_global(global);
        }

        for func in module.functions() {
            self.run_function(func);
        }
    }

    /// Run the pass on a global variable.
    fn run_global(&mut self,
                  _: &lang::Global<V>) {
        // do nothing unless overidden
    }

    /// Run the pass on a function.
    fn run_function(&mut self,
                    function: &lang::Function<V>) {

        for bb in function.blocks() {
            self.run_block(bb);
        }
    }

    /// Run the pass on a basic block.
    fn run_block(&mut self,
                 block: &lang::Block<V>) {

        for value in block.values() {
            self.run_value_recursive(&value);
        }
    }

    /// Run the pass on a value.
    fn run_value(&mut self,
                 _: &V) {

        panic!("the pass is not implemented");
    }

    fn run_value_recursive(&mut self,
                           value: &V) {

        // Recurse from the deepest node to the root node.
        for val in value.subvalues() {
            self.run_value_recursive(&val);
        }

        self.run_value(value)
    }
}

pub trait Transform<V> : Metadata
    where V: lang::Value
{
    /// Run the pass on an entire module.
    fn run_module(&mut self,
                  module: lang::Module<V>) -> lang::Module<V> {
        module.map_globals(|a| self.run_global(a))
              .map_functions(|a| self.run_function(a))
    }

    /// Run the pass on a global.
    fn run_global(&mut self,
                  global: lang::Global<V>)
        -> lang::Global<V> {

        // do nothing unless overridden
        global
    }

    /// Run the pass on a function.
    fn run_function(&mut self,
                    function: lang::Function<V>)
        -> lang::Function<V> {

        function.map_blocks(|a| self.run_block(a))
    }

    /// Run the pass on a basic block.
    fn run_block(&mut self,
                 block: lang::Block<V>)
        -> lang::Block<V> {

        block.map_values(|a| self.run_value_recursive(a))
    }

    /// Run the pass on a value.
    fn run_value(&mut self,
                 _: V) -> V {

        panic!("the {} pass is not implemented", self.name());
    }

    fn run_value_recursive(&mut self,
                           value: V) -> V {

        // Recurse from the deepest node to the root node.
        let val = value.map_subvalues(|v| self.run_value_recursive(v));
        self.run_value(val)
    }
}

<|endoftext|>


<commit_before>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::slice;
use ffi;
use glib::translate::*;
use TreePath;

impl TreePath {
    pub fn get_indices(&self) -> &[i32] {
        unsafe {
            let mut count = 0;
            let ptr = ffi::gtk_tree_path_get_indices_with_depth(mut_override(self.to_glib_none().0),
                &mut count);
            if ptr.is_null() {
                &[]
            }
            else {
                slice::from_raw_parts(ptr, count as usize)
            }
        }
    }
}
<commit_msg>Return a vector instead of a slice with unbounded lifetime<commit_after>// Copyright 2013-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

use std::slice;
use ffi;
use glib::translate::*;
use TreePath;

impl TreePath {
    pub fn get_indices(&self) -> Vec<i32> {
        unsafe {
            let mut count = 0;
            let ptr = ffi::gtk_tree_path_get_indices_with_depth(mut_override(self.to_glib_none().0),
                &mut count);
            if ptr.is_null() {
                vec![]
            }
            else {
                slice::from_raw_parts(ptr, count as usize).to_owned()
            }
        }
    }
}
<|endoftext|>