<commit_before>use crate::syntax::namespace::Namespace;
use crate::syntax::report::Errors;
use crate::syntax::Atom::{self, *};
use crate::syntax::{Derive, Doc};
use proc_macro2::Ident;
use syn::parse::{ParseStream, Parser as _};
use syn::{Attribute, Error, LitStr, Path, Result, Token};

#[derive(Default)]
pub struct Parser<'a> {
    pub doc: Option<&'a mut Doc>,
    pub derives: Option<&'a mut Vec<Derive>>,
    pub repr: Option<&'a mut Option<Atom>>,
    pub namespace: Option<&'a mut Namespace>,
    pub cxx_name: Option<&'a mut Option<Ident>>,
    pub rust_name: Option<&'a mut Option<Ident>>,
}

pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
    for attr in attrs {
        if attr.path.is_ident("doc") {
            match parse_doc_attribute.parse2(attr.tokens.clone()) {
                Ok(lit) => {
                    if let Some(doc) = &mut parser.doc {
                        doc.push(lit);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("derive") {
            match attr.parse_args_with(|attr: ParseStream| parse_derive_attribute(cx, attr)) {
                Ok(attr) => {
                    if let Some(derives) = &mut parser.derives {
                        derives.extend(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("repr") {
            match attr.parse_args_with(parse_repr_attribute) {
                Ok(attr) => {
                    if let Some(repr) = &mut parser.repr {
                        **repr = Some(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("namespace") {
            match parse_namespace_attribute.parse2(attr.tokens.clone()) {
                Ok(attr) => {
                    if let Some(namespace) = &mut parser.namespace {
                        **namespace = attr;
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("cxx_name") {
            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
                Ok(attr) => {
                    if let Some(cxx_name) = &mut parser.cxx_name {
                        **cxx_name = Some(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("rust_name") {
            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
                Ok(attr) => {
                    if let Some(rust_name) = &mut parser.rust_name {
                        **rust_name = Some(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        }
        return cx.error(attr, "unsupported attribute");
    }
}

fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
    input.parse::<Token![=]>()?;
    let lit: LitStr = input.parse()?;
    Ok(lit)
}

fn parse_derive_attribute(cx: &mut Errors, input: ParseStream) -> Result<Vec<Derive>> {
    let paths = input.parse_terminated::<Path, Token![,]>(Path::parse_mod_style)?;

    let mut derives = Vec::new();
    for path in paths {
        if let Some(ident) = path.get_ident() {
            if let Some(derive) = Derive::from(ident) {
                derives.push(derive);
                continue;
            }
        }
        cx.error(path, "unsupported derive");
    }
    Ok(derives)
}

fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
    let begin = input.cursor();
    let ident: Ident = input.parse()?;
    if let Some(atom) = Atom::from(&ident) {
        match atom {
            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize if input.is_empty() => {
                return Ok(atom);
            }
            _ => {}
        }
    }
    Err(Error::new_spanned(
        begin.token_stream(),
        "unrecognized repr",
    ))
}

fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
    input.parse::<Token![=]>()?;
    let namespace = input.parse::<Namespace>()?;
    Ok(namespace)
}

fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
    input.parse::<Token![=]>()?;
    if input.peek(LitStr) {
        let lit: LitStr = input.parse()?;
        lit.parse()
    } else {
        input.parse()
    }
}
<commit_msg>Work around clippy needless_update lint on attrs::Parser<commit_after>use crate::syntax::namespace::Namespace;
use crate::syntax::report::Errors;
use crate::syntax::Atom::{self, *};
use crate::syntax::{Derive, Doc};
use proc_macro2::Ident;
use syn::parse::{ParseStream, Parser as _};
use syn::{Attribute, Error, LitStr, Path, Result, Token};

#[derive(Default)]
pub struct Parser<'a> {
    pub doc: Option<&'a mut Doc>,
    pub derives: Option<&'a mut Vec<Derive>>,
    pub repr: Option<&'a mut Option<Atom>>,
    pub namespace: Option<&'a mut Namespace>,
    pub cxx_name: Option<&'a mut Option<Ident>>,
    pub rust_name: Option<&'a mut Option<Ident>>,

    // Suppress clippy needless_update lint ("struct update has no effect, all
    // the fields in the struct have already been specified") when preemptively
    // writing `..Default::default()`.
    pub(crate) _more: (),
}

pub(super) fn parse(cx: &mut Errors, attrs: &[Attribute], mut parser: Parser) {
    for attr in attrs {
        if attr.path.is_ident("doc") {
            match parse_doc_attribute.parse2(attr.tokens.clone()) {
                Ok(lit) => {
                    if let Some(doc) = &mut parser.doc {
                        doc.push(lit);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("derive") {
            match attr.parse_args_with(|attr: ParseStream| parse_derive_attribute(cx, attr)) {
                Ok(attr) => {
                    if let Some(derives) = &mut parser.derives {
                        derives.extend(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("repr") {
            match attr.parse_args_with(parse_repr_attribute) {
                Ok(attr) => {
                    if let Some(repr) = &mut parser.repr {
                        **repr = Some(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("namespace") {
            match parse_namespace_attribute.parse2(attr.tokens.clone()) {
                Ok(attr) => {
                    if let Some(namespace) = &mut parser.namespace {
                        **namespace = attr;
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("cxx_name") {
            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
                Ok(attr) => {
                    if let Some(cxx_name) = &mut parser.cxx_name {
                        **cxx_name = Some(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        } else if attr.path.is_ident("rust_name") {
            match parse_function_alias_attribute.parse2(attr.tokens.clone()) {
                Ok(attr) => {
                    if let Some(rust_name) = &mut parser.rust_name {
                        **rust_name = Some(attr);
                        continue;
                    }
                }
                Err(err) => return cx.push(err),
            }
        }
        return cx.error(attr, "unsupported attribute");
    }
}

fn parse_doc_attribute(input: ParseStream) -> Result<LitStr> {
    input.parse::<Token![=]>()?;
    let lit: LitStr = input.parse()?;
    Ok(lit)
}

fn parse_derive_attribute(cx: &mut Errors, input: ParseStream) -> Result<Vec<Derive>> {
    let paths = input.parse_terminated::<Path, Token![,]>(Path::parse_mod_style)?;

    let mut derives = Vec::new();
    for path in paths {
        if let Some(ident) = path.get_ident() {
            if let Some(derive) = Derive::from(ident) {
                derives.push(derive);
                continue;
            }
        }
        cx.error(path, "unsupported derive");
    }
    Ok(derives)
}

fn parse_repr_attribute(input: ParseStream) -> Result<Atom> {
    let begin = input.cursor();
    let ident: Ident = input.parse()?;
    if let Some(atom) = Atom::from(&ident) {
        match atom {
            U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64 | Isize if input.is_empty() => {
                return Ok(atom);
            }
            _ => {}
        }
    }
    Err(Error::new_spanned(
        begin.token_stream(),
        "unrecognized repr",
    ))
}

fn parse_namespace_attribute(input: ParseStream) -> Result<Namespace> {
    input.parse::<Token![=]>()?;
    let namespace = input.parse::<Namespace>()?;
    Ok(namespace)
}

fn parse_function_alias_attribute(input: ParseStream) -> Result<Ident> {
    input.parse::<Token![=]>()?;
    if input.peek(LitStr) {
        let lit: LitStr = input.parse()?;
        lit.parse()
    } else {
        input.parse()
    }
}
<|endoftext|>


<commit_before>use std::vec::Vec;

pub fn matches(pattern: &str, candidate: &str) -> bool {
    let pattern: Vec<&str> = pattern.split("/").collect();
    let candidate: Vec<&str> = candidate.split("/").collect();
    matches_segments(&pattern[..], &candidate[..])
}

fn matches_segments(pattern: &[&str], candidate: &[&str]) -> bool {
    if pattern.len() == 0 {
        // We need to run out of pattern and candidate at the same time
        candidate.len() == 0
    } else if candidate.len() == 0 {
        // If the candidate ends before the pattern, reject it. The candidate
        // must not be more general than the pattern
        false
    } else if pattern[0] == "**" {
        // In this case the path can span multiple directories. For simplicity,
        // it's not allowed to have a partial match here, so the pattern must be
        // exactly "**". Here we'll follow a "use it or lose it strategy" where
        // each recursive time we either consume a candidate segment, or we stop consuming.
        matches_segments(&pattern[1..], candidate) || matches_segments(pattern, &candidate[1..])
    } else if pattern[0].contains("*") {
        // This is the case where we have a single wildcard in in the pattern. We'll defer
        // to a helper function to help
        matches_glob(pattern[0], candidate[0]) && matches_segments(&pattern[1..], &candidate[1..])
    } else {
        // If there are no wildcards, we can do a straight comparison on the segments
        pattern[0] == candidate[0] && matches_segments(&pattern[1..], &candidate[1..])
    }
}

fn matches_glob(pattern: &str, candidate: &str) -> bool {
    if pattern.len() == 0 {
        candidate.len() == 0
    } else if candidate.len() == 0 {
        pattern == "*"
    } else if pattern.chars().nth(0).unwrap() == '*' {
        // Use it or lose it. We either consume a candidate charactor or stop consuming
        matches_glob(&pattern[1..], candidate) || matches_glob(pattern, &candidate[1..])
    } else {
        pattern.chars().nth(0).unwrap() == candidate.chars().nth(0).unwrap() &&
        matches_glob(&pattern[1..], &candidate[1..])
    }
}

#[cfg(test)]
mod tests {
    use super::matches_glob;

    #[test]
    fn matches_glob_works_on_empty_strings() {
        assert_eq!(true, matches_glob("", ""));
        assert_eq!(false, matches_glob("a", ""));
        assert_eq!(false, matches_glob("", "a"));
    }

    #[test]
    fn matches_glob_works_with_full_wildcard_pattern() {
        assert_eq!(true, matches_glob("*", "*"));
        assert_eq!(true, matches_glob("*", "a"));
        assert_eq!(true, matches_glob("*", "abc*"));
        assert_eq!(true, matches_glob("*", "*abc"));
    }

    #[test]
    fn matches_glob_works_with_partial_wildcard_pattern() {
        assert_eq!(true, matches_glob("*a", "cba"));
        assert_eq!(true, matches_glob("*a", "a"));
        assert_eq!(false, matches_glob("*a", "b"));

        assert_eq!(true, matches_glob("a*", "abc"));
        assert_eq!(true, matches_glob("a*", "a"));
        assert_eq!(false, matches_glob("a*", "b"));

        assert_eq!(true, matches_glob("a*b", "afb"));
        assert_eq!(true, matches_glob("a*b", "afghb"));
        assert_eq!(true, matches_glob("a*b", "ab"));
        assert_eq!(false, matches_glob("a*b", "afghbf"));
    }

    #[test]
    fn matches_glob_works_with_multiple_wildcards() {
        assert_eq!(true, matches_glob("*a*", "cba"));
        assert_eq!(true, matches_glob("*a*", "a"));
        assert_eq!(true, matches_glob("*a*", "abc"));
        assert_eq!(true, matches_glob("*a*", "bac"));
        assert_eq!(false, matches_glob("*a*", "b"));

        assert_eq!(true, matches_glob("a*a*", "aba"));
        assert_eq!(true, matches_glob("a*a*", "abaf"));
    }
}
<commit_msg>Added glob matching and tests for single string glob matching<commit_after>use std::vec::Vec;

pub fn matches(pattern: &str, candidate: &str) -> bool {
    let pattern: Vec<&str> = pattern.split("/").collect();
    let candidate: Vec<&str> = candidate.split("/").collect();
    matches_segments(&pattern[..], &candidate[..])
}

fn matches_segments(pattern: &[&str], candidate: &[&str]) -> bool {
    if pattern.len() == 0 {
        // We need to run out of pattern and candidate at the same time
        candidate.len() == 0
    } else if candidate.len() == 0 {
        // If the candidate ends before the pattern, reject it. The candidate
        // must not be more general than the pattern
        false
    } else if pattern[0] == "**" {
        // In this case the path can span multiple directories. For simplicity,
        // it's not allowed to have a partial match here, so the pattern must be
        // exactly "**". Here we'll follow a "use it or lose it strategy" where
        // each recursive time we either consume a candidate segment, or we stop consuming.
        matches_segments(&pattern[1..], candidate) || matches_segments(pattern, &candidate[1..])
    } else if pattern[0].contains("*") {
        // This is the case where we have a single wildcard in in the pattern. We'll defer
        // to a helper function to help
        matches_glob(pattern[0], candidate[0]) && matches_segments(&pattern[1..], &candidate[1..])
    } else {
        // If there are no wildcards, we can do a straight comparison on the segments
        pattern[0] == candidate[0] && matches_segments(&pattern[1..], &candidate[1..])
    }
}

fn matches_glob(pattern: &str, candidate: &str) -> bool {
    if pattern.len() == 0 {
        candidate.len() == 0
    } else if candidate.len() == 0 {
        pattern == "*"
    } else if pattern.chars().nth(0).unwrap() == '*' {
        // Use it or lose it. We either consume a candidate charactor or stop consuming
        matches_glob(&pattern[1..], candidate) || matches_glob(pattern, &candidate[1..])
    } else {
        pattern.chars().nth(0).unwrap() == candidate.chars().nth(0).unwrap() &&
        matches_glob(&pattern[1..], &candidate[1..])
    }
}

#[cfg(test)]
mod tests {
    use super::matches_glob;

    #[test]
    fn matches_glob_works_on_empty_strings() {
        assert_eq!(true, matches_glob("", ""));
        assert_eq!(false, matches_glob("a", ""));
        assert_eq!(false, matches_glob("", "a"));
    }

    #[test]
    fn matches_glob_works_with_full_wildcard_pattern() {
        assert_eq!(true, matches_glob("*", "*"));
        assert_eq!(true, matches_glob("*", "a"));
        assert_eq!(true, matches_glob("*", "abc*"));
        assert_eq!(true, matches_glob("*", "*abc"));
    }

    #[test]
    fn matches_glob_works_with_partial_wildcard_pattern() {
        assert_eq!(true, matches_glob("*a", "cba"));
        assert_eq!(true, matches_glob("*a", "a"));
        assert_eq!(false, matches_glob("*a", "b"));

        assert_eq!(true, matches_glob("a*", "abc"));
        assert_eq!(true, matches_glob("a*", "a"));
        assert_eq!(false, matches_glob("a*", "b"));

        assert_eq!(true, matches_glob("a*b", "afb"));
        assert_eq!(true, matches_glob("a*b", "afghb"));
        assert_eq!(true, matches_glob("a*b", "ab"));
        assert_eq!(false, matches_glob("a*b", "afghbf"));
    }

    #[test]
    fn matches_glob_works_with_multiple_wildcards() {
        assert_eq!(true, matches_glob("*a*", "cba"));
        assert_eq!(true, matches_glob("*a*", "a"));
        assert_eq!(true, matches_glob("*a*", "abc"));
        assert_eq!(true, matches_glob("*a*", "bac"));
        assert_eq!(false, matches_glob("*a*", "b"));
        assert_eq!(false, matches_glob("*a*", ""));

        assert_eq!(true, matches_glob("a*a*", "aba"));
        assert_eq!(true, matches_glob("a*a*", "abaf"));
    }
}
<|endoftext|>


<commit_before>//! `GraphMap<N, E>` is an undirected graph where node values are mapping keys.

use std::hash::{Hash};
use std::collections::HashMap;
use std::iter::Cloned;
use std::collections::hash_map::{
    Keys,
};
use std::collections::hash_map::Iter as HashmapIter;
use std::slice::{
    Iter,
};
use std::fmt;
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};

use IntoWeightedEdge;

/// `GraphMap<N, E>` is an undirected graph, with generic node values `N` and edge weights `E`.
///
/// It uses an combined adjacency list and sparse adjacency matrix representation, using **O(|V|
/// + |E|)** space, and allows testing for edge existance in constant time.
///
/// The node type `N` must implement `Copy` and will be used as node identifier, duplicated
/// into several places in the data structure.
/// It must be suitable as a hash table key (implementing `Eq + Hash`).
/// The node type must also implement `Ord` so that the implementation can
/// order the pair (`a`, `b`) for an edge connecting any two nodes `a` and `b`.
///
/// `GraphMap` does not allow parallel edges, but self loops are allowed.
#[derive(Clone)]
pub struct GraphMap<N, E> {
    nodes: HashMap<N, Vec<N>>,
    edges: HashMap<(N, N), E>,
}

impl<N: Eq + Hash + fmt::Debug, E: fmt::Debug> fmt::Debug for GraphMap<N, E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

/// Use their natual order to map the node pair (a, b) to a canonical edge id.
#[inline]
fn edge_key<N: Copy + Ord>(a: N, b: N) -> (N, N) {
    if a <= b { (a, b) } else { (b, a) }
}

/// A trait group for `GraphMap`'s node identifier.
pub trait NodeTrait : Copy + Ord + Hash {}
impl<N> NodeTrait for N where N: Copy + Ord + Hash {}

impl<N, E> GraphMap<N, E>
    where N: NodeTrait
{
    /// Create a new `GraphMap`.
    pub fn new() -> Self {
        GraphMap {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    /// Create a new `GraphMap` with estimated capacity.
    pub fn with_capacity(nodes: usize, edges: usize) -> Self {
        GraphMap {
            nodes: HashMap::with_capacity(nodes),
            edges: HashMap::with_capacity(edges),
        }
    }

    /// Return the current node and edge capacity of the graph.
    pub fn capacity(&self) -> (usize, usize) {
        (self.nodes.capacity(), self.edges.capacity())
    }

    /// Create a new `GraphMap` from an iterable of edges.
    ///
    /// Node values are taken directly from the list.
    /// Edge weights `E` may either be specified in the list,
    /// or they are filled with default values.
    ///
    /// Nodes are inserted automatically to match the edges.
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let gr = GraphMap::<_, ()>::from_edges(&[
    ///     (0, 1), (0, 2), (0, 3),
    ///     (1, 2), (1, 3),
    ///     (2, 3),
    /// ]);
    /// ```
    pub fn from_edges<I>(iterable: I) -> Self
        where I: IntoIterator,
              I::Item: IntoWeightedEdge<N, E>
    {
        Self::from_iter(iterable)
    }

    /// Return the number of nodes in the graph.
    pub fn node_count(&self) -> usize {
        self.nodes.len()
    }

    /// Return the number of edges in the graph.
    pub fn edge_count(&self) -> usize {
        self.edges.len()
    }

    /// Remove all nodes and edges
    pub fn clear(&mut self) {
        self.nodes.clear();
        self.edges.clear();
    }

    /// Add node `n` to the graph.
    pub fn add_node(&mut self, n: N) -> N {
        self.nodes.entry(n).or_insert_with(|| Vec::new());
        n
    }

    /// Return `true` if node `n` was removed.
    pub fn remove_node(&mut self, n: N) -> bool {
        let successors = match self.nodes.remove(&n) {
            None => return false,
            Some(sus) => sus,
        };
        for succ in successors.into_iter() {
            // remove all successor links
            self.remove_single_edge(&succ, &n);
            // Remove all edge values
            self.edges.remove(&edge_key(n, succ));
        }
        true
    }

    /// Return `true` if the node is contained in the graph.
    pub fn contains_node(&self, n: N) -> bool {
        self.nodes.contains_key(&n)
    }

    /// Add an edge connecting `a` and `b` to the graph, with associated
    /// data `weight`.
    ///
    /// Inserts nodes `a` and/or `b` if they aren't already part of the graph.
    ///
    /// Return `None` if the edge did not previously exist, otherwise,
    /// the associated data is updated and the old value is returned
    /// as `Some(old_weight)`.
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    /// assert_eq!(g.node_count(), 2);
    /// assert_eq!(g.edge_count(), 1);
    /// ```
    pub fn add_edge(&mut self, a: N, b: N, weight: E) -> Option<E> {
        if let old @ Some(_) = self.edges.insert(edge_key(a, b), weight) {
            old
        } else {
            // insert in the adjacency list if it's a new edge
            self.nodes.entry(a)
                      .or_insert_with(|| Vec::with_capacity(1))
                      .push(b);
            if a != b {
                self.nodes.entry(b)
                          .or_insert_with(|| Vec::with_capacity(1))
                          .push(a);
            }
            None
        }
    }

    /// Remove successor relation from a to b
    ///
    /// Return `true` if it did exist.
    fn remove_single_edge(&mut self, a: &N, b: &N) -> bool {
        match self.nodes.get_mut(a) {
            None => false,
            Some(sus) => {
                match sus.iter().position(|elt| elt == b) {
                    Some(index) => { sus.swap_remove(index); true }
                    None => false,
                }
            }
        }
    }

    /// Remove edge from `a` to `b` from the graph and return the edge weight.
    ///
    /// Return `None` if the edge didn't exist.
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    ///
    /// let edge_data = g.remove_edge(2, 1);
    /// assert_eq!(edge_data, Some(-1));
    /// assert_eq!(g.edge_count(), 0);
    /// ```
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E> {
        let exist1 = self.remove_single_edge(&a, &b);
        let exist2 = if a != b { self.remove_single_edge(&b, &a) } else { exist1 };
        let weight = self.edges.remove(&edge_key(a, b));
        debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
        weight
    }

    /// Return `true` if the edge connecting `a` with `b` is contained in the graph.
    pub fn contains_edge(&self, a: N, b: N) -> bool {
        self.edges.contains_key(&edge_key(a, b))
    }

    /// Return an iterator over the nodes of the graph.
    ///
    /// Iterator element type is `N`.
    pub fn nodes(&self) -> Nodes<N> {
        Nodes{iter: self.nodes.keys().cloned()}
    }

    /// Return an iterator over the nodes that are connected with `from` by edges.
    ///
    /// If the node `from` does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is `N`.
    pub fn neighbors(&self, from: N) -> Neighbors<N> {
        Neighbors{iter:
            match self.nodes.get(&from) {
                Some(neigh) => neigh.iter(),
                None => [].iter(),
            }.cloned()
        }
    }

    /// Return an iterator over the nodes that are connected with `from` by edges,
    /// paired with the edge weight.
    ///
    /// If the node `from` does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is `(N, &E)`.
    pub fn edges(&self, from: N) -> Edges<N, E> {
        Edges {
            from: from,
            iter: self.neighbors(from),
            edges: &self.edges,
        }
    }

    /// Return a reference to the edge weight connecting `a` with `b`, or
    /// `None` if the edge does not exist in the graph.
    pub fn edge_weight(&self, a: N, b: N) -> Option<&E> {
        self.edges.get(&edge_key(a, b))
    }

    /// Return a mutable reference to the edge weight connecting `a` with `b`, or
    /// `None` if the edge does not exist in the graph.
    pub fn edge_weight_mut(&mut self, a: N, b: N) -> Option<&mut E> {
        self.edges.get_mut(&edge_key(a, b))
    }

    /// Return an iterator over all edges of the graph with their weight in arbitrary order.
    ///
    /// Iterator element type is `(N, N, &E)`
    pub fn all_edges(&self) -> AllEdges<N, E> {
        AllEdges {
            inner: self.edges.iter()
        }
    }
}

/// Create a new `GraphMap` from an iterable of edges.
impl<N, E, Item> FromIterator<Item> for GraphMap<N, E>
    where Item: IntoWeightedEdge<N, E>,
          N: NodeTrait,
{
    fn from_iter<I>(iterable: I) -> Self
        where I: IntoIterator<Item=Item>,
    {
        let iter = iterable.into_iter();
        let (low, _) = iter.size_hint();
        let mut g = Self::with_capacity(0, low);
        g.extend(iter);
        g
    }
}

/// Extend the graph from an iterable of edges.
///
/// Nodes are inserted automatically to match the edges.
impl<N, E, Item> Extend<Item> for GraphMap<N, E>
    where Item: IntoWeightedEdge<N, E>,
          N: NodeTrait,
{
    fn extend<I>(&mut self, iterable: I)
        where I: IntoIterator<Item=Item>,
    {
        let iter = iterable.into_iter();
        let (low, _) = iter.size_hint();
        self.edges.reserve(low);

        for elt in iter {
            let (source, target, weight) = elt.into_weighted_edge();
            self.add_edge(source, target, weight);
        }
    }
}

/// Utitily macro -- reinterpret passed in macro arguments as items
macro_rules! items {
    ($($item:item)*) => ($($item)*);
}

macro_rules! iterator_wrap {
    ($name: ident <$($typarm:tt),*> where { $($bounds: tt)* }
     item: $item: ty,
     iter: $iter: ty,
     ) => (
        items! {
            pub struct $name <$($typarm),*> where $($bounds)* {
                iter: $iter,
            }
            impl<$($typarm),*> Iterator for $name <$($typarm),*>
                where $($bounds)*
            {
                type Item = $item;
                #[inline]
                fn next(&mut self) -> Option<Self::Item> {
                    self.iter.next()
                }

                #[inline]
                fn size_hint(&self) -> (usize, Option<usize>) {
                    self.iter.size_hint()
                }
            }
        }
    );
}

iterator_wrap! {
    Nodes <'a, N> where { N: 'a + NodeTrait }
    item: N,
    iter: Cloned<Keys<'a, N, Vec<N>>>,
}

impl<'a, N: 'a + NodeTrait> ExactSizeIterator for Nodes<'a, N> { }

iterator_wrap! {
    Neighbors <'a, N> where { N: 'a + NodeTrait }
    item: N,
    iter: Cloned<Iter<'a, N>>,
}

impl<'a, N: 'a + NodeTrait> DoubleEndedIterator for Neighbors<'a, N> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back()
    }
}

impl<'a, N: 'a + NodeTrait> ExactSizeIterator for Neighbors<'a, N> { }

pub struct Edges<'a, N, E: 'a> where N: 'a + NodeTrait {
    from: N,
    edges: &'a HashMap<(N, N), E>,
    iter: Neighbors<'a, N>,
}

impl<'a, N, E> Iterator for Edges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, &'a E);
    fn next(&mut self) -> Option<(N, &'a E)>
    {
        match self.iter.next() {
            None => None,
            Some(b) => {
                let a = self.from;
                match self.edges.get(&edge_key(a, b)) {
                    None => unreachable!(),
                    Some(edge) => {
                        Some((b, edge))
                    }
                }
            }
        }
    }
}

pub struct AllEdges<'a, N, E: 'a> where N: 'a + NodeTrait {
    inner: HashmapIter<'a, (N, N), E>
}

impl<'a, N, E> Iterator for AllEdges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, N, &'a E);
    fn next(&mut self) -> Option<Self::Item>
    {
        match self.inner.next() {
            None => None,
            Some((&(a, b), v)) => Some((a, b, v))
        }
    }
}

/// Index `GraphMap` by node pairs to access edge weights.
impl<N, E> Index<(N, N)> for GraphMap<N, E>
    where N: NodeTrait
{
    type Output = E;
    fn index(&self, index: (N, N)) -> &E
    {
        self.edge_weight(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}

/// Index `GraphMap` by node pairs to access edge weights.
impl<N, E> IndexMut<(N, N)> for GraphMap<N, E>
    where N: NodeTrait
{
    fn index_mut(&mut self, index: (N, N)) -> &mut E
    {
        self.edge_weight_mut(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}
<commit_msg>impl Default for GraphMap<commit_after>//! `GraphMap<N, E>` is an undirected graph where node values are mapping keys.

use std::hash::{Hash};
use std::collections::HashMap;
use std::iter::Cloned;
use std::collections::hash_map::{
    Keys,
};
use std::collections::hash_map::Iter as HashmapIter;
use std::slice::{
    Iter,
};
use std::fmt;
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};

use IntoWeightedEdge;

/// `GraphMap<N, E>` is an undirected graph, with generic node values `N` and edge weights `E`.
///
/// It uses an combined adjacency list and sparse adjacency matrix representation, using **O(|V|
/// + |E|)** space, and allows testing for edge existance in constant time.
///
/// The node type `N` must implement `Copy` and will be used as node identifier, duplicated
/// into several places in the data structure.
/// It must be suitable as a hash table key (implementing `Eq + Hash`).
/// The node type must also implement `Ord` so that the implementation can
/// order the pair (`a`, `b`) for an edge connecting any two nodes `a` and `b`.
///
/// `GraphMap` does not allow parallel edges, but self loops are allowed.
#[derive(Clone)]
pub struct GraphMap<N, E> {
    nodes: HashMap<N, Vec<N>>,
    edges: HashMap<(N, N), E>,
}

impl<N: Eq + Hash + fmt::Debug, E: fmt::Debug> fmt::Debug for GraphMap<N, E> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.nodes.fmt(f)
    }
}

/// Use their natual order to map the node pair (a, b) to a canonical edge id.
#[inline]
fn edge_key<N: Copy + Ord>(a: N, b: N) -> (N, N) {
    if a <= b { (a, b) } else { (b, a) }
}

/// A trait group for `GraphMap`'s node identifier.
pub trait NodeTrait : Copy + Ord + Hash {}
impl<N> NodeTrait for N where N: Copy + Ord + Hash {}

impl<N, E> GraphMap<N, E>
    where N: NodeTrait
{
    /// Create a new `GraphMap`.
    pub fn new() -> Self {
        GraphMap {
            nodes: HashMap::new(),
            edges: HashMap::new(),
        }
    }

    /// Create a new `GraphMap` with estimated capacity.
    pub fn with_capacity(nodes: usize, edges: usize) -> Self {
        GraphMap {
            nodes: HashMap::with_capacity(nodes),
            edges: HashMap::with_capacity(edges),
        }
    }

    /// Return the current node and edge capacity of the graph.
    pub fn capacity(&self) -> (usize, usize) {
        (self.nodes.capacity(), self.edges.capacity())
    }

    /// Create a new `GraphMap` from an iterable of edges.
    ///
    /// Node values are taken directly from the list.
    /// Edge weights `E` may either be specified in the list,
    /// or they are filled with default values.
    ///
    /// Nodes are inserted automatically to match the edges.
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let gr = GraphMap::<_, ()>::from_edges(&[
    ///     (0, 1), (0, 2), (0, 3),
    ///     (1, 2), (1, 3),
    ///     (2, 3),
    /// ]);
    /// ```
    pub fn from_edges<I>(iterable: I) -> Self
        where I: IntoIterator,
              I::Item: IntoWeightedEdge<N, E>
    {
        Self::from_iter(iterable)
    }

    /// Return the number of nodes in the graph.
    pub fn node_count(&self) -> usize {
        self.nodes.len()
    }

    /// Return the number of edges in the graph.
    pub fn edge_count(&self) -> usize {
        self.edges.len()
    }

    /// Remove all nodes and edges
    pub fn clear(&mut self) {
        self.nodes.clear();
        self.edges.clear();
    }

    /// Add node `n` to the graph.
    pub fn add_node(&mut self, n: N) -> N {
        self.nodes.entry(n).or_insert_with(|| Vec::new());
        n
    }

    /// Return `true` if node `n` was removed.
    pub fn remove_node(&mut self, n: N) -> bool {
        let successors = match self.nodes.remove(&n) {
            None => return false,
            Some(sus) => sus,
        };
        for succ in successors.into_iter() {
            // remove all successor links
            self.remove_single_edge(&succ, &n);
            // Remove all edge values
            self.edges.remove(&edge_key(n, succ));
        }
        true
    }

    /// Return `true` if the node is contained in the graph.
    pub fn contains_node(&self, n: N) -> bool {
        self.nodes.contains_key(&n)
    }

    /// Add an edge connecting `a` and `b` to the graph, with associated
    /// data `weight`.
    ///
    /// Inserts nodes `a` and/or `b` if they aren't already part of the graph.
    ///
    /// Return `None` if the edge did not previously exist, otherwise,
    /// the associated data is updated and the old value is returned
    /// as `Some(old_weight)`.
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    /// assert_eq!(g.node_count(), 2);
    /// assert_eq!(g.edge_count(), 1);
    /// ```
    pub fn add_edge(&mut self, a: N, b: N, weight: E) -> Option<E> {
        if let old @ Some(_) = self.edges.insert(edge_key(a, b), weight) {
            old
        } else {
            // insert in the adjacency list if it's a new edge
            self.nodes.entry(a)
                      .or_insert_with(|| Vec::with_capacity(1))
                      .push(b);
            if a != b {
                self.nodes.entry(b)
                          .or_insert_with(|| Vec::with_capacity(1))
                          .push(a);
            }
            None
        }
    }

    /// Remove successor relation from a to b
    ///
    /// Return `true` if it did exist.
    fn remove_single_edge(&mut self, a: &N, b: &N) -> bool {
        match self.nodes.get_mut(a) {
            None => false,
            Some(sus) => {
                match sus.iter().position(|elt| elt == b) {
                    Some(index) => { sus.swap_remove(index); true }
                    None => false,
                }
            }
        }
    }

    /// Remove edge from `a` to `b` from the graph and return the edge weight.
    ///
    /// Return `None` if the edge didn't exist.
    ///
    /// ```
    /// use petgraph::GraphMap;
    ///
    /// let mut g = GraphMap::new();
    /// g.add_edge(1, 2, -1);
    ///
    /// let edge_data = g.remove_edge(2, 1);
    /// assert_eq!(edge_data, Some(-1));
    /// assert_eq!(g.edge_count(), 0);
    /// ```
    pub fn remove_edge(&mut self, a: N, b: N) -> Option<E> {
        let exist1 = self.remove_single_edge(&a, &b);
        let exist2 = if a != b { self.remove_single_edge(&b, &a) } else { exist1 };
        let weight = self.edges.remove(&edge_key(a, b));
        debug_assert!(exist1 == exist2 && exist1 == weight.is_some());
        weight
    }

    /// Return `true` if the edge connecting `a` with `b` is contained in the graph.
    pub fn contains_edge(&self, a: N, b: N) -> bool {
        self.edges.contains_key(&edge_key(a, b))
    }

    /// Return an iterator over the nodes of the graph.
    ///
    /// Iterator element type is `N`.
    pub fn nodes(&self) -> Nodes<N> {
        Nodes{iter: self.nodes.keys().cloned()}
    }

    /// Return an iterator over the nodes that are connected with `from` by edges.
    ///
    /// If the node `from` does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is `N`.
    pub fn neighbors(&self, from: N) -> Neighbors<N> {
        Neighbors{iter:
            match self.nodes.get(&from) {
                Some(neigh) => neigh.iter(),
                None => [].iter(),
            }.cloned()
        }
    }

    /// Return an iterator over the nodes that are connected with `from` by edges,
    /// paired with the edge weight.
    ///
    /// If the node `from` does not exist in the graph, return an empty iterator.
    ///
    /// Iterator element type is `(N, &E)`.
    pub fn edges(&self, from: N) -> Edges<N, E> {
        Edges {
            from: from,
            iter: self.neighbors(from),
            edges: &self.edges,
        }
    }

    /// Return a reference to the edge weight connecting `a` with `b`, or
    /// `None` if the edge does not exist in the graph.
    pub fn edge_weight(&self, a: N, b: N) -> Option<&E> {
        self.edges.get(&edge_key(a, b))
    }

    /// Return a mutable reference to the edge weight connecting `a` with `b`, or
    /// `None` if the edge does not exist in the graph.
    pub fn edge_weight_mut(&mut self, a: N, b: N) -> Option<&mut E> {
        self.edges.get_mut(&edge_key(a, b))
    }

    /// Return an iterator over all edges of the graph with their weight in arbitrary order.
    ///
    /// Iterator element type is `(N, N, &E)`
    pub fn all_edges(&self) -> AllEdges<N, E> {
        AllEdges {
            inner: self.edges.iter()
        }
    }
}

/// Create a new `GraphMap` from an iterable of edges.
impl<N, E, Item> FromIterator<Item> for GraphMap<N, E>
    where Item: IntoWeightedEdge<N, E>,
          N: NodeTrait,
{
    fn from_iter<I>(iterable: I) -> Self
        where I: IntoIterator<Item=Item>,
    {
        let iter = iterable.into_iter();
        let (low, _) = iter.size_hint();
        let mut g = Self::with_capacity(0, low);
        g.extend(iter);
        g
    }
}

/// Extend the graph from an iterable of edges.
///
/// Nodes are inserted automatically to match the edges.
impl<N, E, Item> Extend<Item> for GraphMap<N, E>
    where Item: IntoWeightedEdge<N, E>,
          N: NodeTrait,
{
    fn extend<I>(&mut self, iterable: I)
        where I: IntoIterator<Item=Item>,
    {
        let iter = iterable.into_iter();
        let (low, _) = iter.size_hint();
        self.edges.reserve(low);

        for elt in iter {
            let (source, target, weight) = elt.into_weighted_edge();
            self.add_edge(source, target, weight);
        }
    }
}

/// Utitily macro -- reinterpret passed in macro arguments as items
macro_rules! items {
    ($($item:item)*) => ($($item)*);
}

macro_rules! iterator_wrap {
    ($name: ident <$($typarm:tt),*> where { $($bounds: tt)* }
     item: $item: ty,
     iter: $iter: ty,
     ) => (
        items! {
            pub struct $name <$($typarm),*> where $($bounds)* {
                iter: $iter,
            }
            impl<$($typarm),*> Iterator for $name <$($typarm),*>
                where $($bounds)*
            {
                type Item = $item;
                #[inline]
                fn next(&mut self) -> Option<Self::Item> {
                    self.iter.next()
                }

                #[inline]
                fn size_hint(&self) -> (usize, Option<usize>) {
                    self.iter.size_hint()
                }
            }
        }
    );
}

iterator_wrap! {
    Nodes <'a, N> where { N: 'a + NodeTrait }
    item: N,
    iter: Cloned<Keys<'a, N, Vec<N>>>,
}

impl<'a, N: 'a + NodeTrait> ExactSizeIterator for Nodes<'a, N> { }

iterator_wrap! {
    Neighbors <'a, N> where { N: 'a + NodeTrait }
    item: N,
    iter: Cloned<Iter<'a, N>>,
}

impl<'a, N: 'a + NodeTrait> DoubleEndedIterator for Neighbors<'a, N> {
    fn next_back(&mut self) -> Option<Self::Item> {
        self.iter.next_back()
    }
}

impl<'a, N: 'a + NodeTrait> ExactSizeIterator for Neighbors<'a, N> { }

pub struct Edges<'a, N, E: 'a> where N: 'a + NodeTrait {
    from: N,
    edges: &'a HashMap<(N, N), E>,
    iter: Neighbors<'a, N>,
}

impl<'a, N, E> Iterator for Edges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, &'a E);
    fn next(&mut self) -> Option<(N, &'a E)>
    {
        match self.iter.next() {
            None => None,
            Some(b) => {
                let a = self.from;
                match self.edges.get(&edge_key(a, b)) {
                    None => unreachable!(),
                    Some(edge) => {
                        Some((b, edge))
                    }
                }
            }
        }
    }
}

pub struct AllEdges<'a, N, E: 'a> where N: 'a + NodeTrait {
    inner: HashmapIter<'a, (N, N), E>
}

impl<'a, N, E> Iterator for AllEdges<'a, N, E>
    where N: 'a + NodeTrait, E: 'a
{
    type Item = (N, N, &'a E);
    fn next(&mut self) -> Option<Self::Item>
    {
        match self.inner.next() {
            None => None,
            Some((&(a, b), v)) => Some((a, b, v))
        }
    }
}

/// Index `GraphMap` by node pairs to access edge weights.
impl<N, E> Index<(N, N)> for GraphMap<N, E>
    where N: NodeTrait
{
    type Output = E;
    fn index(&self, index: (N, N)) -> &E
    {
        self.edge_weight(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}

/// Index `GraphMap` by node pairs to access edge weights.
impl<N, E> IndexMut<(N, N)> for GraphMap<N, E>
    where N: NodeTrait
{
    fn index_mut(&mut self, index: (N, N)) -> &mut E
    {
        self.edge_weight_mut(index.0, index.1).expect("GraphMap::index: no such edge")
    }
}

/// Create a new empty `GraphMap`.
impl<N, E> Default for GraphMap<N, E>
    where N: NodeTrait,
{
    fn default() -> Self { GraphMap::new() }
}
<|endoftext|>


<commit_before>#[doc = "Sorts items by type"];

export mk_pass;

fn mk_pass() -> pass {
    sort_pass::mk_pass { |item1, item2|
        fn score(item: doc::itemtag) -> int {
            alt item {
              doc::consttag(_) { 0 }
              doc::tytag(_) { 1 }
              doc::enumtag(_) { 2 }
              doc::restag(_) { 3 }
              doc::ifacetag(_) { 4 }
              doc::impltag(_) { 5 }
              doc::fntag(_) { 6 }
              doc::modtag(_) { 7 }
              _ { fail }
            }
        }

        score(item1) <= score(item2)
    }
}

#[test]
fn test() {
    let source =
        "mod imod { } \
         const iconst: int = 0; \
         fn ifn() { } \
         enum ienum { ivar } \
         resource ires(a: bool) { } \
         iface iiface { fn a(); } \
         impl iimpl for int { fn a() { } } \
         type itype = int;";
    astsrv::from_str(source) {|srv|
        let doc = extract::from_srv(srv, "");
        let doc = mk_pass()(srv, doc);
        assert doc.topmod.items[0].name() == "iconst";
        assert doc.topmod.items[1].name() == "itype";
        assert doc.topmod.items[2].name() == "ienum";
        assert doc.topmod.items[3].name() == "ires";
        assert doc.topmod.items[4].name() == "iiface";
        assert doc.topmod.items[5].name() == "iimpl";
        assert doc.topmod.items[6].name() == "ifn";
        assert doc.topmod.items[7].name() == "imod";
    }
}
<commit_msg>rustdoc: Sort native mods<commit_after>#[doc = "Sorts items by type"];

export mk_pass;

fn mk_pass() -> pass {
    sort_pass::mk_pass { |item1, item2|
        fn score(item: doc::itemtag) -> int {
            alt item {
              doc::consttag(_) { 0 }
              doc::tytag(_) { 1 }
              doc::enumtag(_) { 2 }
              doc::restag(_) { 3 }
              doc::ifacetag(_) { 4 }
              doc::impltag(_) { 5 }
              doc::fntag(_) { 6 }
              doc::modtag(_) { 7 }
              doc::nmodtag(_) { 8 }
            }
        }

        score(item1) <= score(item2)
    }
}

#[test]
fn test() {
    let source =
        "mod imod { } \
         native mod inmod { } \
         const iconst: int = 0; \
         fn ifn() { } \
         enum ienum { ivar } \
         resource ires(a: bool) { } \
         iface iiface { fn a(); } \
         impl iimpl for int { fn a() { } } \
         type itype = int;";
    astsrv::from_str(source) {|srv|
        let doc = extract::from_srv(srv, "");
        let doc = mk_pass()(srv, doc);
        assert doc.topmod.items[0].name() == "iconst";
        assert doc.topmod.items[1].name() == "itype";
        assert doc.topmod.items[2].name() == "ienum";
        assert doc.topmod.items[3].name() == "ires";
        assert doc.topmod.items[4].name() == "iiface";
        assert doc.topmod.items[5].name() == "iimpl";
        assert doc.topmod.items[6].name() == "ifn";
        assert doc.topmod.items[7].name() == "imod";
        assert doc.topmod.items[8].name() == "inmod";
    }
}
<|endoftext|>


<commit_before>// Note: More specifically this lint is largely inspired (aka copied) from
// *rustc*'s
// [`missing_doc`].
//
// [`missing_doc`]: https://github.com/rust-lang/rust/blob/cf9cf7c923eb01146971429044f216a3ca905e06/compiler/rustc_lint/src/builtin.rs#L415
//

use clippy_utils::attrs::is_doc_hidden;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:** Warns if there is missing doc for any documentable item
    /// (public or private).
    ///
    /// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS`
    /// allowed-by-default lint for
    /// public members, but has no way to enforce documentation of private items.
    /// This lint fixes that.
    ///
    /// **Known problems:** None.
    pub MISSING_DOCS_IN_PRIVATE_ITEMS,
    restriction,
    "detects missing documentation for public and private members"
}

pub struct MissingDoc {
    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,
}

impl Default for MissingDoc {
    #[must_use]
    fn default() -> Self {
        Self::new()
    }
}

impl MissingDoc {
    #[must_use]
    pub fn new() -> Self {
        Self {
            doc_hidden_stack: vec![false],
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    fn check_missing_docs_attrs(
        &self,
        cx: &LateContext<'_>,
        attrs: &[ast::Attribute],
        sp: Span,
        article: &'static str,
        desc: &'static str,
    ) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // `#[doc(hidden)]` disables missing_docs check.
        if self.doc_hidden() {
            return;
        }

        if sp.from_expansion() {
            return;
        }

        let has_doc = attrs
            .iter()
            .any(|a| a.doc_str().is_some());
        if !has_doc {
            span_lint(
                cx,
                MISSING_DOCS_IN_PRIVATE_ITEMS,
                sp,
                &format!("missing documentation for {} {}", article, desc),
            );
        }
    }
}

impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);

impl<'tcx> LateLintPass<'tcx> for MissingDoc {
    fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) {
        let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs);
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
        let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
        self.check_missing_docs_attrs(cx, attrs, krate.item.inner, "the", "crate");
    }

    fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
        match it.kind {
            hir::ItemKind::Fn(..) => {
                // ignore main()
                if it.ident.name == sym::main {
                    let def_key = cx.tcx.hir().def_key(it.def_id);
                    if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
                        return;
                    }
                }
            },
            hir::ItemKind::Const(..)
            | hir::ItemKind::Enum(..)
            | hir::ItemKind::Mod(..)
            | hir::ItemKind::Static(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Trait(..)
            | hir::ItemKind::TraitAlias(..)
            | hir::ItemKind::TyAlias(..)
            | hir::ItemKind::Union(..)
            | hir::ItemKind::OpaqueTy(..) => {},
            hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod { .. }
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::Impl { .. }
            | hir::ItemKind::Use(..) => return,
        };

        let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());

        let attrs = cx.tcx.hir().attrs(it.hir_id());
        self.check_missing_docs_attrs(cx, attrs, it.span, article, desc);
    }

    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
        let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());

        let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
        self.check_missing_docs_attrs(cx, attrs, trait_item.span, article, desc);
    }

    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
        // If the method is an impl for a trait, don't doc.
        match cx.tcx.associated_item(impl_item.def_id).container {
            ty::TraitContainer(_) => return,
            ty::ImplContainer(cid) => {
                if cx.tcx.impl_trait_ref(cid).is_some() {
                    return;
                }
            },
        }

        let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
        let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
        self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc);
    }

    fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
        if !sf.is_positional() {
            let attrs = cx.tcx.hir().attrs(sf.hir_id);
            self.check_missing_docs_attrs(cx, attrs, sf.span, "a", "struct field");
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
        let attrs = cx.tcx.hir().attrs(v.id);
        self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant");
    }
}
<commit_msg>Introduce OwnerNode::Crate.<commit_after>// Note: More specifically this lint is largely inspired (aka copied) from
// *rustc*'s
// [`missing_doc`].
//
// [`missing_doc`]: https://github.com/rust-lang/rust/blob/cf9cf7c923eb01146971429044f216a3ca905e06/compiler/rustc_lint/src/builtin.rs#L415
//

use clippy_utils::attrs::is_doc_hidden;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::ast;
use rustc_hir as hir;
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::source_map::Span;
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:** Warns if there is missing doc for any documentable item
    /// (public or private).
    ///
    /// **Why is this bad?** Doc is good. *rustc* has a `MISSING_DOCS`
    /// allowed-by-default lint for
    /// public members, but has no way to enforce documentation of private items.
    /// This lint fixes that.
    ///
    /// **Known problems:** None.
    pub MISSING_DOCS_IN_PRIVATE_ITEMS,
    restriction,
    "detects missing documentation for public and private members"
}

pub struct MissingDoc {
    /// Stack of whether #[doc(hidden)] is set
    /// at each level which has lint attributes.
    doc_hidden_stack: Vec<bool>,
}

impl Default for MissingDoc {
    #[must_use]
    fn default() -> Self {
        Self::new()
    }
}

impl MissingDoc {
    #[must_use]
    pub fn new() -> Self {
        Self {
            doc_hidden_stack: vec![false],
        }
    }

    fn doc_hidden(&self) -> bool {
        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
    }

    fn check_missing_docs_attrs(
        &self,
        cx: &LateContext<'_>,
        attrs: &[ast::Attribute],
        sp: Span,
        article: &'static str,
        desc: &'static str,
    ) {
        // If we're building a test harness, then warning about
        // documentation is probably not really relevant right now.
        if cx.sess().opts.test {
            return;
        }

        // `#[doc(hidden)]` disables missing_docs check.
        if self.doc_hidden() {
            return;
        }

        if sp.from_expansion() {
            return;
        }

        let has_doc = attrs
            .iter()
            .any(|a| a.doc_str().is_some());
        if !has_doc {
            span_lint(
                cx,
                MISSING_DOCS_IN_PRIVATE_ITEMS,
                sp,
                &format!("missing documentation for {} {}", article, desc),
            );
        }
    }
}

impl_lint_pass!(MissingDoc => [MISSING_DOCS_IN_PRIVATE_ITEMS]);

impl<'tcx> LateLintPass<'tcx> for MissingDoc {
    fn enter_lint_attrs(&mut self, _: &LateContext<'tcx>, attrs: &'tcx [ast::Attribute]) {
        let doc_hidden = self.doc_hidden() || is_doc_hidden(attrs);
        self.doc_hidden_stack.push(doc_hidden);
    }

    fn exit_lint_attrs(&mut self, _: &LateContext<'tcx>, _: &'tcx [ast::Attribute]) {
        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
    }

    fn check_crate(&mut self, cx: &LateContext<'tcx>, krate: &'tcx hir::Crate<'_>) {
        let attrs = cx.tcx.hir().attrs(hir::CRATE_HIR_ID);
        self.check_missing_docs_attrs(cx, attrs, krate.module().inner, "the", "crate");
    }

    fn check_item(&mut self, cx: &LateContext<'tcx>, it: &'tcx hir::Item<'_>) {
        match it.kind {
            hir::ItemKind::Fn(..) => {
                // ignore main()
                if it.ident.name == sym::main {
                    let def_key = cx.tcx.hir().def_key(it.def_id);
                    if def_key.parent == Some(hir::def_id::CRATE_DEF_INDEX) {
                        return;
                    }
                }
            },
            hir::ItemKind::Const(..)
            | hir::ItemKind::Enum(..)
            | hir::ItemKind::Mod(..)
            | hir::ItemKind::Static(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Trait(..)
            | hir::ItemKind::TraitAlias(..)
            | hir::ItemKind::TyAlias(..)
            | hir::ItemKind::Union(..)
            | hir::ItemKind::OpaqueTy(..) => {},
            hir::ItemKind::ExternCrate(..)
            | hir::ItemKind::ForeignMod { .. }
            | hir::ItemKind::GlobalAsm(..)
            | hir::ItemKind::Impl { .. }
            | hir::ItemKind::Use(..) => return,
        };

        let (article, desc) = cx.tcx.article_and_description(it.def_id.to_def_id());

        let attrs = cx.tcx.hir().attrs(it.hir_id());
        self.check_missing_docs_attrs(cx, attrs, it.span, article, desc);
    }

    fn check_trait_item(&mut self, cx: &LateContext<'tcx>, trait_item: &'tcx hir::TraitItem<'_>) {
        let (article, desc) = cx.tcx.article_and_description(trait_item.def_id.to_def_id());

        let attrs = cx.tcx.hir().attrs(trait_item.hir_id());
        self.check_missing_docs_attrs(cx, attrs, trait_item.span, article, desc);
    }

    fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx hir::ImplItem<'_>) {
        // If the method is an impl for a trait, don't doc.
        match cx.tcx.associated_item(impl_item.def_id).container {
            ty::TraitContainer(_) => return,
            ty::ImplContainer(cid) => {
                if cx.tcx.impl_trait_ref(cid).is_some() {
                    return;
                }
            },
        }

        let (article, desc) = cx.tcx.article_and_description(impl_item.def_id.to_def_id());
        let attrs = cx.tcx.hir().attrs(impl_item.hir_id());
        self.check_missing_docs_attrs(cx, attrs, impl_item.span, article, desc);
    }

    fn check_field_def(&mut self, cx: &LateContext<'tcx>, sf: &'tcx hir::FieldDef<'_>) {
        if !sf.is_positional() {
            let attrs = cx.tcx.hir().attrs(sf.hir_id);
            self.check_missing_docs_attrs(cx, attrs, sf.span, "a", "struct field");
        }
    }

    fn check_variant(&mut self, cx: &LateContext<'tcx>, v: &'tcx hir::Variant<'_>) {
        let attrs = cx.tcx.hir().attrs(v.id);
        self.check_missing_docs_attrs(cx, attrs, v.span, "a", "variant");
    }
}
<|endoftext|>


<commit_before>use std::str::Chars;
use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;

pub struct TokenValue<'a> {
  token: Token,
  value: &'a str
}

/// Lexer
pub struct Lexer<'a> {
  line: int,
  column: int,
  pos: int,
  iter: Chars<'a>,
  curr_ch: Option<char>,
  done: bool
}

/// Lexer tokens.
pub enum Token {
  PLUS,
  MINUS,
  INTEGER, // Any type of integer
  IDEN, // Identifier
  LPAREN,
  RPAREN,
  COLON
}

impl<'a> TokenValue<'a> {
  pub fn new(tok: Token, val: &'a str) -> TokenValue<'a> {
    TokenValue {
      token: tok,
      value: val
    }
  }
}

impl Eq for Token {
  fn eq(&self, other: &Token) -> bool {
    match *self {
      PLUS => match *other { PLUS => true, _ => false },
      MINUS => match *other { MINUS => true, _ => false },
      INTEGER => match *other { INTEGER => true, _ => false },
      IDEN => match *other { IDEN => true, _ => false },
      LPAREN => match *other { LPAREN => true, _ => false },
      RPAREN => match *other { RPAREN => true, _ => false },
      COLON => match *other { COLON => true, _ => false }
    }
  }
}

impl Show for Token {
  fn fmt(&self, f: &mut Formatter) -> fmt::Result {
    let c = match *self {
      PLUS => &"+",
      MINUS => &"-",
      INTEGER => &"integer",
      IDEN => &"iden",
      LPAREN => &"(",
      RPAREN => &")",
      COLON => ":"
    };

    write!(f.buf, "({})", c)
  }
}

pub fn verify_iden_start(ch: char) -> bool {

  match ch {
    'A' => true,
    'a' => true,
    'B' => true,
    'b' => true,
    'C' => true,
    'c' => true,
    'D' => true,
    'd' => true,
    'E' => true,
    'e' => true,
    'F' => true,
    'f' => true,
    'G' => true,
    'g' => true,
    'H' => true,
    'h' => true,
    'I' => true,
    'i' => true,
    'J' => true,
    'j' => true,
    'K' => true,
    'k' => true,
    'L' => true,
    'l' => true,
    'M' => true,
    'm' => true,
    'N' => true,
    'n' => true,
    'O' => true,
    'o' => true,
    'P' => true,
    'p' => true,
    'Q' => true,
    'q' => true,
    'R' => true,
    'r' => true,
    'S' => true,
    's' => true,
    'T' => true,
    't' => true,
    'U' => true,
    'u' => true,
    'V' => true,
    'v' => true,
    'W' => true,
    'w' => true,
    'Y' => true,
    'y' => true,
    'Z' => true,
    'z' => true,
    '+' => true,
    '-' => true,
    '*' => true,
    _ => false
  }
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
  // Create a new iterator
  let mut iter = ch.chars().peekable();

  // Verify the first character.
  if !verify_iden_start(iter.next().unwrap()) {
    return false;
  }

  for x in iter {
    match x {
      '\n' => return false,
      '\r' => return false,
      ' ' => return false,
      _  =>  if !verify_iden_start(x) { return false }
    }
  }

  true
}

impl<'a> Lexer<'a> {
  pub fn new(input: &'a str) -> Lexer<'a> {
    let it = input.chars();
    Lexer {
      line: 0,
      column: 0,
      pos: 0,
      iter: it,
      curr_ch: None,
      done: false
    }
  }

  pub fn bump(&mut self) {
    self.curr_ch = self.iter.next();
  }

  pub fn nextch_is(&mut self, ch: char) -> bool {
    self.bump();
    self.curr_ch.unwrap() == ch
  }

  pub fn next_token(&mut self) -> Option<TokenValue<'a>> {

    for c in self.iter {
      match c {
        '(' => return Some(TokenValue::new(LPAREN, &"(")),
        ')' => return Some(TokenValue::new(RPAREN, &")")),
        '+' => return Some(TokenValue::new(PLUS, &"+")),
        '-' => return Some(TokenValue::new(MINUS, &"-")),
        ':' => return Some(TokenValue::new(COLON, &":")),
        '9' => return Some(TokenValue::new(INTEGER, &"9")),
        '8' => return Some(TokenValue::new(INTEGER, &"8")),
        '7' => return Some(TokenValue::new(INTEGER, &"7")),
        '6' => return Some(TokenValue::new(INTEGER, &"6")),
        '5' => return Some(TokenValue::new(INTEGER, &"5")),
        '4' => return Some(TokenValue::new(INTEGER, &"4")),
        '3' => return Some(TokenValue::new(INTEGER, &"3")),
        '2' => return Some(TokenValue::new(INTEGER, &"2")),
        '1' => return Some(TokenValue::new(INTEGER, &"1")),
        '0' => return Some(TokenValue::new(INTEGER, &"0")),
        _ => {
          println!("--");
          let mut it = self.iter;

          // Try and parse an identifier
          let mut iden = ~"";
          let mut prev = ~"";
          iden.push_char(c);

          for a in it {
            // FIXME(TheHydroImpulse): A huge fucking hack.
            if !is_iden(iden) && is_iden(prev) {
              return Some(TokenValue::new(IDEN, unsafe {
                transmute(prev.as_slice())
              }));
            }

            prev = iden.clone();
            iden.push_char(a);
            println!("iden = {}, is_iden(iden) = {}, prev = {}, ch = {}",
                iden, is_iden(iden), prev, a);
          }

          if !is_iden(iden) && is_iden(prev) {
            return Some(TokenValue::new(IDEN, unsafe {
              transmute(prev.as_slice())
            }));
          }
        }
      }
    }

    None
  }

}

#[cfg(test)]
mod test {
  use super::Lexer;
  use super::LPAREN;
  use super::TokenValue;

  #[test]
  fn bump() {
    let mut lex = Lexer::new(&"Hello World");
    lex.bump();
    assert_eq!(lex.curr_ch.unwrap(), 'H');
  }

  #[test]
  fn nextch() {
    let mut lex = Lexer::new(&"Woot");
    assert!(lex.nextch_is('W'));
  }

  #[test]
  fn next_token() {
    // Should spit out two tokens (LPAREN,RPAREN)
    let mut lex = Lexer::new(&"()");
    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &")");
  }

  #[test]
  fn return_complex_tokens() {
    let mut lex = Lexer::new(&"(+(():830");

    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &"+");
    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &"(");
    assert!(lex.next_token().unwrap().value == &")");
    assert!(lex.next_token().unwrap().value == &":");
    assert!(lex.next_token().unwrap().value == &"8");
    assert!(lex.next_token().unwrap().value == &"3");
    assert!(lex.next_token().unwrap().value == &"0");
  }

  #[test]
  fn should_tokenize_identifier() {
    let mut lex = Lexer::new(&"(let)");
    println!("1");
    assert_eq!(lex.next_token().unwrap().value, &"(");
    assert_eq!(lex.next_token().unwrap().value, &"let");
  }

}<commit_msg>indentation<commit_after>use std::str::Chars;
use std::fmt::{Show,Formatter};
use std::fmt;
use std::cast::transmute;

pub struct TokenValue<'a> {
    token: Token,
    value: &'a str
}

impl<'a> TokenValue<'a> {
    pub fn new(tok: Token, val: &'a str) -> TokenValue<'a> {
        TokenValue {
            token: tok,
            value: val
        }
    }
}

/// Lexer
pub struct Lexer<'a> {
    iter: *mut Chars<'a>,
    done: bool
}

/// Lexer tokens.
pub enum Token {
    PLUS,
    MINUS,
    INTEGER, // Any type of integer
    IDEN, // Identifier
    LPAREN,
    RPAREN,
    COLON
}

// An iden is identified by:
// /^([A-Za-z-+*^][A-Za-z0-9-_]*)$/
pub fn is_iden<'b>(ch: &'b str) -> bool {
    // Create a new iterator
    let mut iter = ch.chars().peekable();

    // Verify the first character.
    if !verify_iden_start(iter.next().unwrap()) {
        return false;
    }

    for x in iter {
        match x {
            '\n' => return false,
            '\r' => return false,
            ' ' => return false,
            _  =>  if !verify_iden_start(x) { return false }
        }
    }

    true
}

impl<'a> Lexer<'a> {
    pub fn new(input: &'a str) -> Lexer<'a> {
        let it = ~input.chars();
        Lexer {
            iter: unsafe { transmute(it) },
            done: false
        }
    }

    pub fn next_token(&mut self) -> Option<TokenValue<'a>> {
        unsafe {
            for c in *self.iter {
                match c {
                    '(' => return Some(TokenValue::new(LPAREN, &"(")),
                    ')' => return Some(TokenValue::new(RPAREN, &")")),
                    '+' => return Some(TokenValue::new(PLUS, &"+")),
                    '-' => return Some(TokenValue::new(MINUS, &"-")),
                    ':' => return Some(TokenValue::new(COLON, &":")),
                    '9' => return Some(TokenValue::new(INTEGER, &"9")),
                    '8' => return Some(TokenValue::new(INTEGER, &"8")),
                    '7' => return Some(TokenValue::new(INTEGER, &"7")),
                    '6' => return Some(TokenValue::new(INTEGER, &"6")),
                    '5' => return Some(TokenValue::new(INTEGER, &"5")),
                    '4' => return Some(TokenValue::new(INTEGER, &"4")),
                    '3' => return Some(TokenValue::new(INTEGER, &"3")),
                    '2' => return Some(TokenValue::new(INTEGER, &"2")),
                    '1' => return Some(TokenValue::new(INTEGER, &"1")),
                    '0' => return Some(TokenValue::new(INTEGER, &"0")),
                    _ => {

                        // Try and parse an identifier
                        let mut iden = ~"";
                        let mut prev = ~"";
                        iden.push_char(c);

                        for a in *self.iter {
                            // FIXME(TheHydroImpulse): A huge fucking hack.
                            if !is_iden(iden) && is_iden(prev) {
                            return Some(TokenValue::new(IDEN, unsafe {
                              transmute(prev.as_slice())
                            }));
                            }

                            prev = iden.clone();
                            iden.push_char(a);
                        }

                        if !is_iden(iden) && is_iden(prev) {
                            return Some(TokenValue::new(IDEN, unsafe {
                            transmute(prev.as_slice())
                            }));
                        }
                    }
                }
            }
        }
        None
    }
}

pub fn verify_iden_start(ch: char) -> bool {
    match ch {
        'A' => true,
        'a' => true,
        'B' => true,
        'b' => true,
        'C' => true,
        'c' => true,
        'D' => true,
        'd' => true,
        'E' => true,
        'e' => true,
        'F' => true,
        'f' => true,
        'G' => true,
        'g' => true,
        'H' => true,
        'h' => true,
        'I' => true,
        'i' => true,
        'J' => true,
        'j' => true,
        'K' => true,
        'k' => true,
        'L' => true,
        'l' => true,
        'M' => true,
        'm' => true,
        'N' => true,
        'n' => true,
        'O' => true,
        'o' => true,
        'P' => true,
        'p' => true,
        'Q' => true,
        'q' => true,
        'R' => true,
        'r' => true,
        'S' => true,
        's' => true,
        'T' => true,
        't' => true,
        'U' => true,
        'u' => true,
        'V' => true,
        'v' => true,
        'W' => true,
        'w' => true,
        'Y' => true,
        'y' => true,
        'Z' => true,
        'z' => true,
        '+' => true,
        '-' => true,
        '*' => true,
        _ => false
    }
}

impl Eq for Token {
    fn eq(&self, other: &Token) -> bool {
        match *self {
            PLUS => match *other { PLUS => true, _ => false },
            MINUS => match *other { MINUS => true, _ => false },
            INTEGER => match *other { INTEGER => true, _ => false },
            IDEN => match *other { IDEN => true, _ => false },
            LPAREN => match *other { LPAREN => true, _ => false },
            RPAREN => match *other { RPAREN => true, _ => false },
            COLON => match *other { COLON => true, _ => false }
        }
    }
}

impl Show for Token {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        let c = match *self {
            PLUS => &"+",
            MINUS => &"-",
            INTEGER => &"integer",
            IDEN => &"iden",
            LPAREN => &"(",
            RPAREN => &")",
            COLON => ":"
        };

        write!(f.buf, "({})", c)
    }
}

#[cfg(test)]
mod test {
    use super::Lexer;
    use super::LPAREN;
    use super::TokenValue;

    #[test]
    fn next_token() {
        // Should spit out two tokens (LPAREN,RPAREN)
        let mut lex = Lexer::new(&"()");
        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &")");
    }

    #[test]
    fn return_complex_tokens() {
        let mut lex = Lexer::new(&"(+(():830");

        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &"+");
        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &"(");
        assert!(lex.next_token().unwrap().value == &")");
        assert!(lex.next_token().unwrap().value == &":");
        assert!(lex.next_token().unwrap().value == &"8");
        assert!(lex.next_token().unwrap().value == &"3");
        assert!(lex.next_token().unwrap().value == &"0");
    }

    #[test]
    fn should_tokenize_identifier() {
        let mut lex = Lexer::new(&"(let)");

        assert_eq!(lex.next_token().unwrap().value, &"(");
        assert_eq!(lex.next_token().unwrap().value, &"let");
    }
}<|endoftext|>


<commit_before>// Copyright 2018 The Exonum Team
//
// 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 exonum::blockchain::{ExecutionError, ExecutionResult, Transaction};
use exonum::crypto::{CryptoHash, PublicKey};
use exonum::messages::Message;
use exonum::storage::Fork;

use CRYPTOCURRENCY_SERVICE_ID;
use schema::CurrencySchema;

/// Error codes emitted by wallet transactions during execution.
#[derive(Debug, Fail)]
#[repr(u8)]
pub enum Error {
    /// Wallet already exists.
    ///
    /// Can be emitted by `CreateWallet`.
    #[fail(display = "Wallet already exists")]
    WalletAlreadyExists = 0,

    /// Sender doesn't exist.
    ///
    /// Can be emitted by `Transfer`.
    #[fail(display = "Sender doesn't exist")]
    SenderNotFound = 1,

    /// Receiver doesn't exist.
    ///
    /// Can be emitted by `Transfer` or `Issue`.
    #[fail(display = "Receiver doesn't exist")]
    ReceiverNotFound = 2,

    /// Insufficient currency amount.
    ///
    /// Can be emitted by `Transfer`.
    #[fail(display = "Insufficient currency amount")]
    InsufficientCurrencyAmount = 3,
}

impl From<Error> for ExecutionError {
    fn from(value: Error) -> ExecutionError {
        let description = format!("{}", value);
        ExecutionError::with_description(value as u8, description)
    }
}

transactions! {
    pub WalletTransactions {
        const SERVICE_ID = CRYPTOCURRENCY_SERVICE_ID;

        /// Transfer `amount` of the currency from one wallet to another.
        struct Transfer {
            from:    &PublicKey,
            to:      &PublicKey,
            amount:  u64,
            seed:    u64,
        }

        /// Issue `amount` of the currency to the `wallet`.
        struct Issue {
            pub_key:  &PublicKey,
            amount:  u64,
            seed:    u64,
        }

        /// Create wallet with the given `name`.
        struct CreateWallet {
            pub_key: &PublicKey,
            name:    &str,
        }
    }
}

impl Transaction for Transfer {
    fn verify(&self) -> bool {
        self.verify_signature(self.from())
    }

    fn execute(&self, fork: &mut Fork) -> ExecutionResult {
        let mut schema = CurrencySchema::new(fork);

        let from = self.from();
        let to = self.to();
        let hash = self.hash();
        let amount = self.amount();

        let sender = schema.wallet(from).ok_or(Error::SenderNotFound)?;

        let receiver = schema.wallet(to).ok_or(Error::ReceiverNotFound)?;

        if sender.balance() < amount {
            Err(Error::InsufficientCurrencyAmount)?
        }

        schema.decrease_wallet_balance(sender, amount, &hash);
        schema.increase_wallet_balance(receiver, amount, &hash);

        Ok(())
    }
}

impl Transaction for Issue {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, fork: &mut Fork) -> ExecutionResult {
        let mut schema = CurrencySchema::new(fork);
        let pub_key = self.pub_key();
        let hash = self.hash();

        if let Some(wallet) = schema.wallet(pub_key) {
            let amount = self.amount();
            schema.increase_wallet_balance(wallet, amount, &hash);
            Ok(())
        } else {
            Err(Error::ReceiverNotFound)?
        }
    }
}

impl Transaction for CreateWallet {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, fork: &mut Fork) -> ExecutionResult {
        let mut schema = CurrencySchema::new(fork);
        let pub_key = self.pub_key();
        let hash = self.hash();

        if schema.wallet(pub_key).is_none() {
            let name = self.name();
            schema.create_wallet(pub_key, name, &hash);
            Ok(())
        } else {
            Err(Error::WalletAlreadyExists)?
        }
    }
}
<commit_msg>Allow clippy lint<commit_after>// Copyright 2018 The Exonum Team
//
// 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.

#![cfg_attr(feature = "cargo-clippy", allow(redundant_field_names))]

use exonum::blockchain::{ExecutionError, ExecutionResult, Transaction};
use exonum::crypto::{CryptoHash, PublicKey};
use exonum::messages::Message;
use exonum::storage::Fork;

use CRYPTOCURRENCY_SERVICE_ID;
use schema::CurrencySchema;

/// Error codes emitted by wallet transactions during execution.
#[derive(Debug, Fail)]
#[repr(u8)]
pub enum Error {
    /// Wallet already exists.
    ///
    /// Can be emitted by `CreateWallet`.
    #[fail(display = "Wallet already exists")]
    WalletAlreadyExists = 0,

    /// Sender doesn't exist.
    ///
    /// Can be emitted by `Transfer`.
    #[fail(display = "Sender doesn't exist")]
    SenderNotFound = 1,

    /// Receiver doesn't exist.
    ///
    /// Can be emitted by `Transfer` or `Issue`.
    #[fail(display = "Receiver doesn't exist")]
    ReceiverNotFound = 2,

    /// Insufficient currency amount.
    ///
    /// Can be emitted by `Transfer`.
    #[fail(display = "Insufficient currency amount")]
    InsufficientCurrencyAmount = 3,
}

impl From<Error> for ExecutionError {
    fn from(value: Error) -> ExecutionError {
        let description = format!("{}", value);
        ExecutionError::with_description(value as u8, description)
    }
}

transactions! {
    pub WalletTransactions {
        const SERVICE_ID = CRYPTOCURRENCY_SERVICE_ID;

        /// Transfer `amount` of the currency from one wallet to another.
        struct Transfer {
            from:    &PublicKey,
            to:      &PublicKey,
            amount:  u64,
            seed:    u64,
        }

        /// Issue `amount` of the currency to the `wallet`.
        struct Issue {
            pub_key:  &PublicKey,
            amount:  u64,
            seed:    u64,
        }

        /// Create wallet with the given `name`.
        struct CreateWallet {
            pub_key: &PublicKey,
            name:    &str,
        }
    }
}

impl Transaction for Transfer {
    fn verify(&self) -> bool {
        self.verify_signature(self.from())
    }

    fn execute(&self, fork: &mut Fork) -> ExecutionResult {
        let mut schema = CurrencySchema::new(fork);

        let from = self.from();
        let to = self.to();
        let hash = self.hash();
        let amount = self.amount();

        let sender = schema.wallet(from).ok_or(Error::SenderNotFound)?;

        let receiver = schema.wallet(to).ok_or(Error::ReceiverNotFound)?;

        if sender.balance() < amount {
            Err(Error::InsufficientCurrencyAmount)?
        }

        schema.decrease_wallet_balance(sender, amount, &hash);
        schema.increase_wallet_balance(receiver, amount, &hash);

        Ok(())
    }
}

impl Transaction for Issue {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, fork: &mut Fork) -> ExecutionResult {
        let mut schema = CurrencySchema::new(fork);
        let pub_key = self.pub_key();
        let hash = self.hash();

        if let Some(wallet) = schema.wallet(pub_key) {
            let amount = self.amount();
            schema.increase_wallet_balance(wallet, amount, &hash);
            Ok(())
        } else {
            Err(Error::ReceiverNotFound)?
        }
    }
}

impl Transaction for CreateWallet {
    fn verify(&self) -> bool {
        self.verify_signature(self.pub_key())
    }

    fn execute(&self, fork: &mut Fork) -> ExecutionResult {
        let mut schema = CurrencySchema::new(fork);
        let pub_key = self.pub_key();
        let hash = self.hash();

        if schema.wallet(pub_key).is_none() {
            let name = self.name();
            schema.create_wallet(pub_key, name, &hash);
            Ok(())
        } else {
            Err(Error::WalletAlreadyExists)?
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub use super::target_os::syslog::PlatformSyslog;
pub use super::RawDescriptor;

#[cfg(test)]
mod tests {
    use std::ffi::CStr;
    use std::fs::File;
    use std::io::Read;
    use std::io::Seek;
    use std::io::SeekFrom;
    use std::os::unix::io::FromRawFd;

    cfg_if::cfg_if! {
        // ANDROID: b/228881485
        if #[cfg(not(target_os = "android"))] {
            use libc::shm_open;
            use libc::shm_unlink;
            use libc::O_CREAT;
            use libc::O_EXCL;
            use libc::O_RDWR;
        }
    }

    use crate::syslog::*;

    #[test]
    fn fds() {
        ensure_inited().unwrap();
        let mut fds = Vec::new();
        push_descriptors(&mut fds);
        assert!(!fds.is_empty());
        for fd in fds {
            assert!(fd >= 0);
        }
    }

    #[test]
    #[cfg(not(target_os = "android"))] // ANDROID: b/228881485
    fn syslog_file() {
        ensure_inited().unwrap();
        let shm_name = CStr::from_bytes_with_nul(b"/crosvm_shm\0").unwrap();
        let mut file = unsafe {
            shm_unlink(shm_name.as_ptr());
            let fd = shm_open(shm_name.as_ptr(), O_RDWR | O_CREAT | O_EXCL, 0o666);
            assert!(fd >= 0, "error creating shared memory;");
            shm_unlink(shm_name.as_ptr());
            File::from_raw_fd(fd)
        };

        let syslog_file = file.try_clone().expect("error cloning shared memory file");
        let state = State::new(LogConfig {
            pipe: Some(Box::new(syslog_file)),
            ..Default::default()
        })
        .unwrap();

        const TEST_STR: &str = "hello shared memory file";
        state.log(
            &log::RecordBuilder::new()
                .level(Level::Error)
                .args(format_args!("{}", TEST_STR))
                .build(),
        );

        file.seek(SeekFrom::Start(0))
            .expect("error seeking shared memory file");
        let mut buf = String::new();
        file.read_to_string(&mut buf)
            .expect("error reading shared memory file");
        assert!(buf.contains(TEST_STR));
    }
}
<commit_msg>base: use tempfile in syslog_file test<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

pub use super::target_os::syslog::PlatformSyslog;
pub use super::RawDescriptor;

#[cfg(test)]
mod tests {
    use std::io::Read;
    use std::io::Seek;
    use std::io::SeekFrom;

    use crate::syslog::*;

    #[test]
    fn fds() {
        ensure_inited().unwrap();
        let mut fds = Vec::new();
        push_descriptors(&mut fds);
        assert!(!fds.is_empty());
        for fd in fds {
            assert!(fd >= 0);
        }
    }

    #[test]
    fn syslog_file() {
        ensure_inited().unwrap();
        let mut file = tempfile::tempfile().expect("failed to create tempfile");

        let syslog_file = file.try_clone().expect("error cloning shared memory file");
        let state = State::new(LogConfig {
            pipe: Some(Box::new(syslog_file)),
            ..Default::default()
        })
        .unwrap();

        const TEST_STR: &str = "hello shared memory file";
        state.log(
            &log::RecordBuilder::new()
                .level(Level::Error)
                .args(format_args!("{}", TEST_STR))
                .build(),
        );

        file.seek(SeekFrom::Start(0))
            .expect("error seeking shared memory file");
        let mut buf = String::new();
        file.read_to_string(&mut buf)
            .expect("error reading shared memory file");
        assert!(buf.contains(TEST_STR));
    }
}
<|endoftext|>


<commit_before>extern crate nnet;
#[macro_use(ffnn)] extern crate nnet_macros;

use nnet::trainer::backpropagation::IncrementalMSETrainer;
use nnet::params::{TanhNeuralNet, Default};
use nnet::prelude::{NeuralNetTrainer, NeuralNet, MomentumConstant, LearningRate};

ffnn!(XORNeuralNet, 2, 3, 1);

struct MyTrainerParams;

impl MomentumConstant for MyTrainerParams {
  #[inline(always)] fn momentum() -> f64 { 0.0f64 }
}

impl LearningRate for MyTrainerParams {
  #[inline(always)] fn lrate() -> f64 { 0.2f64 }
}

fn main() {
  let xor: [(&[f64], &[f64]); 4] = [
    (&[0f64, 0f64], &[0f64]),
    (&[0f64, 1f64], &[1f64]),
    (&[1f64, 0f64], &[1f64]),
    (&[1f64, 1f64], &[0f64])
  ];

  let mut nn: XORNeuralNet<TanhNeuralNet> = XORNeuralNet::new();

  println!("{:?}", nn);

  {
    let mut trainer: IncrementalMSETrainer<_, _, MyTrainerParams> =
      IncrementalMSETrainer::with_epoch_bound(&mut nn, &xor, 0.01, 5000);
    trainer.finish();
  }

  for ex in xor.iter() {
    nn.predict(ex.0);
    println!("{:?} - prediction = {:?}", ex.0, nn.output);
  }
}<commit_msg>small changes<commit_after>extern crate nnet;
#[macro_use(ffnn)] extern crate nnet_macros;

use nnet::trainer::backpropagation::IncrementalMSETrainer;
use nnet::params::{TanhNeuralNet, Default};
use nnet::prelude::{NeuralNetTrainer, NeuralNet, MomentumConstant, LearningRate};

ffnn!(XORNeuralNet, 2, 3, 1);

struct MyTrainerParams;

impl MomentumConstant for MyTrainerParams {
  #[inline(always)] fn momentum() -> f64 { 0.0f64 }
}

impl LearningRate for MyTrainerParams {
  #[inline(always)] fn lrate() -> f64 { 0.2f64 }
}

fn main() {
  let xor: [(&[f64], &[f64]); 4] = [
    (&[0f64, 0f64], &[0f64]),
    (&[0f64, 1f64], &[1f64]),
    (&[1f64, 0f64], &[1f64]),
    (&[1f64, 1f64], &[0f64])
  ];

  let mut nn: XORNeuralNet<Default> = XORNeuralNet::new();

  println!("{:?}", nn);

  {
    let mut trainer: IncrementalMSETrainer<_, _, MyTrainerParams> =
      IncrementalMSETrainer::with_epoch_bound(&mut nn, &xor, 0.01, 9000);
    trainer.finish();
  }

  for ex in xor.iter() {
    nn.predict(ex.0);
    println!("{:?} - prediction = {:?}", ex.0, nn.output);
  }
}<|endoftext|>


<commit_before>#![allow(clippy::manual_assert)]

mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "5e57faa78aa7661c6000204591558f6665f11abc";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // TODO: impl ~const T {}
    // https://github.com/dtolnay/syn/issues/1051
    "src/test/ui/rfc-2632-const-trait-impl/syntax.rs",

    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/early/closing-args-token.rs",
    "src/test/ui/const-generics/early/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",
    "src/tools/rustfmt/tests/source/trait.rs",
    "src/tools/rustfmt/tests/target/trait.rs",

    // Excessive nesting
    "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",

    // Testing rustfmt on invalid syntax
    "src/tools/rustfmt/tests/coverage/target/comments.rs",
    "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
    "src/tools/rustfmt/tests/parser/issue_4418.rs",
    "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs",
    "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/source/type.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/target/type.rs",

    // Clippy lint lists represented as expressions
    "src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_all.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_cargo.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_complexity.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_correctness.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_internal.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_lints.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_nursery.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_perf.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_restriction.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_style.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
    "src/test/ui/macros/include-single-expr-helper.rs",
    "src/test/ui/macros/include-single-expr-helper-1.rs",
    "src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map_or(true, |e| e != "rs") {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Update test suite to nightly-2022-03-14<commit_after>#![allow(clippy::manual_assert)]

mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "e95b10ba4ac4564ed25f7eef143e3182c33b3902";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // TODO
    "src/test/ui/associated-consts/assoc-const.rs",
    "src/test/ui/generic-associated-types/collections.rs",
    "src/test/ui/generic-associated-types/construct_with_other_type.rs",
    "src/test/ui/generic-associated-types/impl_bounds_ok.rs",
    "src/test/ui/generic-associated-types/issue-76826.rs",
    "src/test/ui/generic-associated-types/issue-88287.rs",
    "src/test/ui/generic-associated-types/issue-91139.rs",
    "src/test/ui/generic-associated-types/issue-92280.rs",
    "src/test/ui/generic-associated-types/iterable.rs",
    "src/test/ui/generic-associated-types/streaming_iterator.rs",
    "src/test/ui/symbol-names/const-generics-demangling.rs",

    // TODO: impl ~const T {}
    // https://github.com/dtolnay/syn/issues/1051
    "src/test/ui/rfc-2632-const-trait-impl/syntax.rs",

    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/early/closing-args-token.rs",
    "src/test/ui/const-generics/early/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",
    "src/tools/rustfmt/tests/source/trait.rs",
    "src/tools/rustfmt/tests/target/trait.rs",

    // Excessive nesting
    "src/test/ui/issues/issue-74564-if-expr-stack-overflow.rs",

    // Testing rustfmt on invalid syntax
    "src/tools/rustfmt/tests/coverage/target/comments.rs",
    "src/tools/rustfmt/tests/parser/issue-4126/invalid.rs",
    "src/tools/rustfmt/tests/parser/issue_4418.rs",
    "src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs",
    "src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/source/type.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs",
    "src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs",
    "src/tools/rustfmt/tests/target/type.rs",

    // Clippy lint lists represented as expressions
    "src/tools/clippy/clippy_lints/src/lib.deprecated.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_all.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_cargo.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_complexity.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_correctness.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_internal.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_lints.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_nursery.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_pedantic.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_perf.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_restriction.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_style.rs",
    "src/tools/clippy/clippy_lints/src/lib.register_suspicious.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
    "src/test/ui/macros/include-single-expr-helper.rs",
    "src/test/ui/macros/include-single-expr-helper-1.rs",
    "src/test/ui/parser/issues/auxiliary/issue-21146-inc.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map_or(true, |e| e != "rs") {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>