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

//! A graph module for use in dataflow, region resolution, and elsewhere.
//!
//! # Interface details
//!
//! You customize the graph by specifying a "node data" type `N` and an
//! "edge data" type `E`. You can then later gain access (mutable or
//! immutable) to these "user-data" bits. Currently, you can only add
//! nodes or edges to the graph. You cannot remove or modify them once
//! added. This could be changed if we have a need.
//!
//! # Implementation details
//!
//! The main tricky thing about this code is the way that edges are
//! stored. The edges are stored in a central array, but they are also
//! threaded onto two linked lists for each node, one for incoming edges
//! and one for outgoing edges. Note that every edge is a member of some
//! incoming list and some outgoing list.  Basically you can load the
//! first index of the linked list from the node data structures (the
//! field `first_edge`) and then, for each edge, load the next index from
//! the field `next_edge`). Each of those fields is an array that should
//! be indexed by the direction (see the type `Direction`).

use bitvec::BitVector;
use std::fmt::{Formatter, Error, Debug};
use std::usize;
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};

#[cfg(test)]
mod tests;

pub struct Graph<N, E> {
    nodes: SnapshotVec<Node<N>>,
    edges: SnapshotVec<Edge<E>>,
}

pub struct Node<N> {
    first_edge: [EdgeIndex; 2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex; 2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

impl<N> SnapshotVecDelegate for Node<N> {
    type Value = Node<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Node<N>>, _: ()) {}
}

impl<N> SnapshotVecDelegate for Edge<N> {
    type Value = Edge<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Edge<N>>, _: ()) {}
}

impl<E: Debug> Debug for Edge<E> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f,
               "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}",
               self.next_edge[0],
               self.next_edge[1],
               self.source,
               self.target,
               self.data)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct NodeIndex(pub usize);

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct EdgeIndex(pub usize);

pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);

// Use a private field here to guarantee no more instances are created:
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Direction {
    repr: usize,
}

pub const OUTGOING: Direction = Direction { repr: 0 };

pub const INCOMING: Direction = Direction { repr: 1 };

impl NodeIndex {
    /// Returns unique id (unique with respect to the graph holding associated node).
    pub fn node_id(&self) -> usize {
        self.0
    }
}

impl EdgeIndex {
    /// Returns unique id (unique with respect to the graph holding associated edge).
    pub fn edge_id(&self) -> usize {
        self.0
    }
}

impl<N: Debug, E: Debug> Graph<N, E> {
    pub fn new() -> Graph<N, E> {
        Graph {
            nodes: SnapshotVec::new(),
            edges: SnapshotVec::new(),
        }
    }

    // # Simple accessors

    #[inline]
    pub fn all_nodes(&self) -> &[Node<N>] {
        &self.nodes
    }

    #[inline]
    pub fn len_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    pub fn all_edges(&self) -> &[Edge<E>] {
        &self.edges
    }

    #[inline]
    pub fn len_edges(&self) -> usize {
        self.edges.len()
    }

    // # Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
            data: data,
        });
        idx
    }

    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
        &mut self.nodes[idx.0].data
    }

    pub fn node_data(&self, idx: NodeIndex) -> &N {
        &self.nodes[idx.0].data
    }

    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
        &self.nodes[idx.0]
    }

    // # Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
        debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);

        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
        let target_first = self.nodes[target.0].first_edge[INCOMING.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data,
        });

        // adjust the firsts for each node target be the next object.
        self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
        self.nodes[target.0].first_edge[INCOMING.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
        &mut self.edges[idx.0].data
    }

    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
        &self.edges[idx.0].data
    }

    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
        &self.edges[idx.0]
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes[node.0].first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges[edge.0].next_edge[dir.repr]
    }

    // # Iterating over nodes, edges

    pub fn each_node<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(NodeIndex, &'a Node<N>) -> bool
    {
        //! Iterates over all edges defined in the graph.
        self.nodes.iter().enumerate().all(|(i, node)| f(NodeIndex(i), node))
    }

    pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(EdgeIndex, &'a Edge<E>) -> bool
    {
        //! Iterates over all edges defined in the graph
        self.edges.iter().enumerate().all(|(i, edge)| f(EdgeIndex(i), edge))
    }

    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, OUTGOING)
    }

    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, INCOMING)
    }

    pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N, E> {
        let first_edge = self.node(source).first_edge[direction.repr];
        AdjacentEdges {
            graph: self,
            direction: direction,
            next: first_edge,
        }
    }

    pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N, E> {
        self.outgoing_edges(source).targets()
    }

    pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N, E> {
        self.incoming_edges(target).sources()
    }

    // # Fixed-point iteration
    //
    // A common use for graphs in our compiler is to perform
    // fixed-point iteration. In this case, each edge represents a
    // constraint, and the nodes themselves are associated with
    // variables or other bitsets. This method facilitates such a
    // computation.

    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
        where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
    {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (i, edge) in self.edges.iter().enumerate() {
                changed |= op(iteration, EdgeIndex(i), edge);
            }
        }
    }

    pub fn depth_traverse<'a>(&'a self,
                              start: NodeIndex,
                              direction: Direction)
                              -> DepthFirstTraversal<'a, N, E> {
        DepthFirstTraversal::with_start_node(self, start, direction)
    }
}

// # Iterators

pub struct AdjacentEdges<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    direction: Direction,
    next: EdgeIndex,
}

impl<'g, N, E> AdjacentEdges<'g, N, E> {
    fn targets(self) -> AdjacentTargets<'g, N, E> {
        AdjacentTargets { edges: self }
    }

    fn sources(self) -> AdjacentSources<'g, N, E> {
        AdjacentSources { edges: self }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        let edge_index = self.next;
        if edge_index == INVALID_EDGE_INDEX {
            return None;
        }

        let edge = self.graph.edge(edge_index);
        self.next = edge.next_edge[self.direction.repr];
        Some((edge_index, edge))
    }
}

pub struct AdjacentTargets<'g, N: 'g, E: 'g>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.target)
    }
}

pub struct AdjacentSources<'g, N: 'g, E: 'g>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.source)
    }
}

pub struct DepthFirstTraversal<'g, N: 'g, E: 'g> {
    graph: &'g Graph<N, E>,
    stack: Vec<NodeIndex>,
    visited: BitVector,
    direction: Direction,
}

impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
        let visited = BitVector::new(graph.len_nodes());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![],
            visited: visited,
            direction: direction
        }
    }

    pub fn with_start_node(graph: &'g Graph<N, E>,
                           start_node: NodeIndex,
                           direction: Direction)
                           -> Self {
        let mut visited = BitVector::new(graph.len_nodes());
        visited.insert(start_node.node_id());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![start_node],
            visited: visited,
            direction: direction
        }
    }

    pub fn reset(&mut self, start_node: NodeIndex) {
        self.stack.truncate(0);
        self.stack.push(start_node);
        self.visited.clear();
        self.visited.insert(start_node.node_id());
    }

    fn visit(&mut self, node: NodeIndex) {
        if self.visited.insert(node.node_id()) {
            self.stack.push(node);
        }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        let next = self.stack.pop();
        if let Some(idx) = next {
            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
                let target = edge.source_or_target(self.direction);
                self.visit(target);
            }
        }
        next
    }
}

pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
    where F: FnMut(EdgeIndex) -> bool
{
    let mut i = 0;
    let n = max_edge_index.0;
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

    pub fn target(&self) -> NodeIndex {
        self.target
    }

    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
        if direction == OUTGOING {
            self.target
        } else {
            self.source
        }
    }
}
<commit_msg>run rustfmt on graph folder<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! A graph module for use in dataflow, region resolution, and elsewhere.
//!
//! # Interface details
//!
//! You customize the graph by specifying a "node data" type `N` and an
//! "edge data" type `E`. You can then later gain access (mutable or
//! immutable) to these "user-data" bits. Currently, you can only add
//! nodes or edges to the graph. You cannot remove or modify them once
//! added. This could be changed if we have a need.
//!
//! # Implementation details
//!
//! The main tricky thing about this code is the way that edges are
//! stored. The edges are stored in a central array, but they are also
//! threaded onto two linked lists for each node, one for incoming edges
//! and one for outgoing edges. Note that every edge is a member of some
//! incoming list and some outgoing list.  Basically you can load the
//! first index of the linked list from the node data structures (the
//! field `first_edge`) and then, for each edge, load the next index from
//! the field `next_edge`). Each of those fields is an array that should
//! be indexed by the direction (see the type `Direction`).

use bitvec::BitVector;
use std::fmt::{Formatter, Error, Debug};
use std::usize;
use snapshot_vec::{SnapshotVec, SnapshotVecDelegate};

#[cfg(test)]
mod tests;

pub struct Graph<N, E> {
    nodes: SnapshotVec<Node<N>>,
    edges: SnapshotVec<Edge<E>>,
}

pub struct Node<N> {
    first_edge: [EdgeIndex; 2], // see module comment
    pub data: N,
}

pub struct Edge<E> {
    next_edge: [EdgeIndex; 2], // see module comment
    source: NodeIndex,
    target: NodeIndex,
    pub data: E,
}

impl<N> SnapshotVecDelegate for Node<N> {
    type Value = Node<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Node<N>>, _: ()) {}
}

impl<N> SnapshotVecDelegate for Edge<N> {
    type Value = Edge<N>;
    type Undo = ();

    fn reverse(_: &mut Vec<Edge<N>>, _: ()) {}
}

impl<E: Debug> Debug for Edge<E> {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        write!(f,
               "Edge {{ next_edge: [{:?}, {:?}], source: {:?}, target: {:?}, data: {:?} }}",
               self.next_edge[0],
               self.next_edge[1],
               self.source,
               self.target,
               self.data)
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct NodeIndex(pub usize);

#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub struct EdgeIndex(pub usize);

pub const INVALID_EDGE_INDEX: EdgeIndex = EdgeIndex(usize::MAX);

// Use a private field here to guarantee no more instances are created:
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Direction {
    repr: usize,
}

pub const OUTGOING: Direction = Direction { repr: 0 };

pub const INCOMING: Direction = Direction { repr: 1 };

impl NodeIndex {
    /// Returns unique id (unique with respect to the graph holding associated node).
    pub fn node_id(&self) -> usize {
        self.0
    }
}

impl EdgeIndex {
    /// Returns unique id (unique with respect to the graph holding associated edge).
    pub fn edge_id(&self) -> usize {
        self.0
    }
}

impl<N: Debug, E: Debug> Graph<N, E> {
    pub fn new() -> Graph<N, E> {
        Graph {
            nodes: SnapshotVec::new(),
            edges: SnapshotVec::new(),
        }
    }

    // # Simple accessors

    #[inline]
    pub fn all_nodes(&self) -> &[Node<N>] {
        &self.nodes
    }

    #[inline]
    pub fn len_nodes(&self) -> usize {
        self.nodes.len()
    }

    #[inline]
    pub fn all_edges(&self) -> &[Edge<E>] {
        &self.edges
    }

    #[inline]
    pub fn len_edges(&self) -> usize {
        self.edges.len()
    }

    // # Node construction

    pub fn next_node_index(&self) -> NodeIndex {
        NodeIndex(self.nodes.len())
    }

    pub fn add_node(&mut self, data: N) -> NodeIndex {
        let idx = self.next_node_index();
        self.nodes.push(Node {
            first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
            data: data,
        });
        idx
    }

    pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
        &mut self.nodes[idx.0].data
    }

    pub fn node_data(&self, idx: NodeIndex) -> &N {
        &self.nodes[idx.0].data
    }

    pub fn node(&self, idx: NodeIndex) -> &Node<N> {
        &self.nodes[idx.0]
    }

    // # Edge construction and queries

    pub fn next_edge_index(&self) -> EdgeIndex {
        EdgeIndex(self.edges.len())
    }

    pub fn add_edge(&mut self, source: NodeIndex, target: NodeIndex, data: E) -> EdgeIndex {
        debug!("graph: add_edge({:?}, {:?}, {:?})", source, target, data);

        let idx = self.next_edge_index();

        // read current first of the list of edges from each node
        let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
        let target_first = self.nodes[target.0].first_edge[INCOMING.repr];

        // create the new edge, with the previous firsts from each node
        // as the next pointers
        self.edges.push(Edge {
            next_edge: [source_first, target_first],
            source: source,
            target: target,
            data: data,
        });

        // adjust the firsts for each node target be the next object.
        self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
        self.nodes[target.0].first_edge[INCOMING.repr] = idx;

        return idx;
    }

    pub fn mut_edge_data(&mut self, idx: EdgeIndex) -> &mut E {
        &mut self.edges[idx.0].data
    }

    pub fn edge_data(&self, idx: EdgeIndex) -> &E {
        &self.edges[idx.0].data
    }

    pub fn edge(&self, idx: EdgeIndex) -> &Edge<E> {
        &self.edges[idx.0]
    }

    pub fn first_adjacent(&self, node: NodeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the index of the first edge adjacent to `node`.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.nodes[node.0].first_edge[dir.repr]
    }

    pub fn next_adjacent(&self, edge: EdgeIndex, dir: Direction) -> EdgeIndex {
        //! Accesses the next edge in a given direction.
        //! This is useful if you wish to modify the graph while walking
        //! the linked list of edges.

        self.edges[edge.0].next_edge[dir.repr]
    }

    // # Iterating over nodes, edges

    pub fn each_node<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(NodeIndex, &'a Node<N>) -> bool
    {
        //! Iterates over all edges defined in the graph.
        self.nodes.iter().enumerate().all(|(i, node)| f(NodeIndex(i), node))
    }

    pub fn each_edge<'a, F>(&'a self, mut f: F) -> bool
        where F: FnMut(EdgeIndex, &'a Edge<E>) -> bool
    {
        //! Iterates over all edges defined in the graph
        self.edges.iter().enumerate().all(|(i, edge)| f(EdgeIndex(i), edge))
    }

    pub fn outgoing_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, OUTGOING)
    }

    pub fn incoming_edges(&self, source: NodeIndex) -> AdjacentEdges<N, E> {
        self.adjacent_edges(source, INCOMING)
    }

    pub fn adjacent_edges(&self, source: NodeIndex, direction: Direction) -> AdjacentEdges<N, E> {
        let first_edge = self.node(source).first_edge[direction.repr];
        AdjacentEdges {
            graph: self,
            direction: direction,
            next: first_edge,
        }
    }

    pub fn successor_nodes(&self, source: NodeIndex) -> AdjacentTargets<N, E> {
        self.outgoing_edges(source).targets()
    }

    pub fn predecessor_nodes(&self, target: NodeIndex) -> AdjacentSources<N, E> {
        self.incoming_edges(target).sources()
    }

    // # Fixed-point iteration
    //
    // A common use for graphs in our compiler is to perform
    // fixed-point iteration. In this case, each edge represents a
    // constraint, and the nodes themselves are associated with
    // variables or other bitsets. This method facilitates such a
    // computation.

    pub fn iterate_until_fixed_point<'a, F>(&'a self, mut op: F)
        where F: FnMut(usize, EdgeIndex, &'a Edge<E>) -> bool
    {
        let mut iteration = 0;
        let mut changed = true;
        while changed {
            changed = false;
            iteration += 1;
            for (i, edge) in self.edges.iter().enumerate() {
                changed |= op(iteration, EdgeIndex(i), edge);
            }
        }
    }

    pub fn depth_traverse<'a>(&'a self,
                              start: NodeIndex,
                              direction: Direction)
                              -> DepthFirstTraversal<'a, N, E> {
        DepthFirstTraversal::with_start_node(self, start, direction)
    }
}

// # Iterators

pub struct AdjacentEdges<'g, N, E>
    where N: 'g,
          E: 'g
{
    graph: &'g Graph<N, E>,
    direction: Direction,
    next: EdgeIndex,
}

impl<'g, N, E> AdjacentEdges<'g, N, E> {
    fn targets(self) -> AdjacentTargets<'g, N, E> {
        AdjacentTargets { edges: self }
    }

    fn sources(self) -> AdjacentSources<'g, N, E> {
        AdjacentSources { edges: self }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentEdges<'g, N, E> {
    type Item = (EdgeIndex, &'g Edge<E>);

    fn next(&mut self) -> Option<(EdgeIndex, &'g Edge<E>)> {
        let edge_index = self.next;
        if edge_index == INVALID_EDGE_INDEX {
            return None;
        }

        let edge = self.graph.edge(edge_index);
        self.next = edge.next_edge[self.direction.repr];
        Some((edge_index, edge))
    }
}

pub struct AdjacentTargets<'g, N: 'g, E: 'g>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentTargets<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.target)
    }
}

pub struct AdjacentSources<'g, N: 'g, E: 'g>
    where N: 'g,
          E: 'g
{
    edges: AdjacentEdges<'g, N, E>,
}

impl<'g, N: Debug, E: Debug> Iterator for AdjacentSources<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        self.edges.next().map(|(_, edge)| edge.source)
    }
}

pub struct DepthFirstTraversal<'g, N: 'g, E: 'g> {
    graph: &'g Graph<N, E>,
    stack: Vec<NodeIndex>,
    visited: BitVector,
    direction: Direction,
}

impl<'g, N: Debug, E: Debug> DepthFirstTraversal<'g, N, E> {
    pub fn new(graph: &'g Graph<N, E>, direction: Direction) -> Self {
        let visited = BitVector::new(graph.len_nodes());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![],
            visited: visited,
            direction: direction,
        }
    }

    pub fn with_start_node(graph: &'g Graph<N, E>,
                           start_node: NodeIndex,
                           direction: Direction)
                           -> Self {
        let mut visited = BitVector::new(graph.len_nodes());
        visited.insert(start_node.node_id());
        DepthFirstTraversal {
            graph: graph,
            stack: vec![start_node],
            visited: visited,
            direction: direction,
        }
    }

    pub fn reset(&mut self, start_node: NodeIndex) {
        self.stack.truncate(0);
        self.stack.push(start_node);
        self.visited.clear();
        self.visited.insert(start_node.node_id());
    }

    fn visit(&mut self, node: NodeIndex) {
        if self.visited.insert(node.node_id()) {
            self.stack.push(node);
        }
    }
}

impl<'g, N: Debug, E: Debug> Iterator for DepthFirstTraversal<'g, N, E> {
    type Item = NodeIndex;

    fn next(&mut self) -> Option<NodeIndex> {
        let next = self.stack.pop();
        if let Some(idx) = next {
            for (_, edge) in self.graph.adjacent_edges(idx, self.direction) {
                let target = edge.source_or_target(self.direction);
                self.visit(target);
            }
        }
        next
    }
}

pub fn each_edge_index<F>(max_edge_index: EdgeIndex, mut f: F)
    where F: FnMut(EdgeIndex) -> bool
{
    let mut i = 0;
    let n = max_edge_index.0;
    while i < n {
        if !f(EdgeIndex(i)) {
            return;
        }
        i += 1;
    }
}

impl<E> Edge<E> {
    pub fn source(&self) -> NodeIndex {
        self.source
    }

    pub fn target(&self) -> NodeIndex {
        self.target
    }

    pub fn source_or_target(&self, direction: Direction) -> NodeIndex {
        if direction == OUTGOING {
            self.target
        } else {
            self.source
        }
    }
}
<|endoftext|>


<commit_before>#![warn(rust_2018_idioms, warnings)]
#![allow(
    clippy::type_complexity,
    clippy::borrow_interior_mutable_const,
    clippy::needless_doctest_main
)]
//! An HTTP Client
//!
//! ```rust
//! use actix_rt::System;
//! use awc::Client;
//!
//! #[actix_rt::main]
//! async fn main() {
//!    let mut client = Client::default();
//!
//!    let response = client.get("http://www.rust-lang.org") // <- Create request builder
//!        .header("User-Agent", "Actix-web")
//!        .send()                             // <- Send http request
//!        .await;
//!
//!     println!("Response: {:?}", response);
//! }
//! ```
use std::cell::RefCell;
use std::convert::TryFrom;
use std::rc::Rc;
use std::time::Duration;

pub use actix_http::{client::Connector, cookie, http};

use actix_http::http::{Error as HttpError, HeaderMap, Method, Uri};
use actix_http::RequestHead;

mod builder;
mod connect;
pub mod error;
mod frozen;
mod request;
mod response;
mod sender;
pub mod test;
pub mod ws;

pub use self::builder::ClientBuilder;
pub use self::connect::BoxedSocket;
pub use self::frozen::{FrozenClientRequest, FrozenSendBuilder};
pub use self::request::ClientRequest;
pub use self::response::{ClientResponse, JsonBody, MessageBody};
pub use self::sender::SendClientRequest;

use self::connect::{Connect, ConnectorWrapper};

/// An HTTP Client
///
/// ```rust
/// use awc::Client;
///
/// #[actix_rt::main]
/// async fn main() {
///     let mut client = Client::default();
///
///     let res = client.get("http://www.rust-lang.org") // <- Create request builder
///         .header("User-Agent", "Actix-web")
///         .send()                             // <- Send http request
///         .await;                             // <- send request and wait for response
///
///      println!("Response: {:?}", res);
/// }
/// ```
#[derive(Clone)]
pub struct Client(Rc<ClientConfig>);

pub(crate) struct ClientConfig {
    pub(crate) connector: RefCell<Box<dyn Connect>>,
    pub(crate) headers: HeaderMap,
    pub(crate) timeout: Option<Duration>,
}

impl Default for Client {
    fn default() -> Self {
        Client(Rc::new(ClientConfig {
            connector: RefCell::new(Box::new(ConnectorWrapper(
                Connector::new().finish(),
            ))),
            headers: HeaderMap::new(),
            timeout: Some(Duration::from_secs(5)),
        }))
    }
}

impl Client {
    /// Create new client instance with default settings.
    pub fn new() -> Client {
        Client::default()
    }

    /// Build client instance.
    pub fn build() -> ClientBuilder {
        ClientBuilder::new()
    }

    /// Construct HTTP request.
    pub fn request<U>(&self, method: Method, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        let mut req = ClientRequest::new(method, url, self.0.clone());

        for (key, value) in self.0.headers.iter() {
            req = req.set_header_if_none(key.clone(), value.clone());
        }
        req
    }

    /// Create `ClientRequest` from `RequestHead`
    ///
    /// It is useful for proxy requests. This implementation
    /// copies all headers and the method.
    pub fn request_from<U>(&self, url: U, head: &RequestHead) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        let mut req = self.request(head.method.clone(), url);
        for (key, value) in head.headers.iter() {
            req = req.set_header_if_none(key.clone(), value.clone());
        }
        req
    }

    /// Construct HTTP *GET* request.
    pub fn get<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::GET, url)
    }

    /// Construct HTTP *HEAD* request.
    pub fn head<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::HEAD, url)
    }

    /// Construct HTTP *PUT* request.
    pub fn put<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::PUT, url)
    }

    /// Construct HTTP *POST* request.
    pub fn post<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::POST, url)
    }

    /// Construct HTTP *PATCH* request.
    pub fn patch<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::PATCH, url)
    }

    /// Construct HTTP *DELETE* request.
    pub fn delete<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::DELETE, url)
    }

    /// Construct HTTP *OPTIONS* request.
    pub fn options<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::OPTIONS, url)
    }

    /// Initialize a WebSocket connection.
    /// Returns a WebSocket connection builder.
    pub fn ws<U>(&self, url: U) -> ws::WebsocketsRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        let mut req = ws::WebsocketsRequest::new(url, self.0.clone());
        for (key, value) in self.0.headers.iter() {
            req.head.headers.insert(key.clone(), value.clone());
        }
        req
    }
}
<commit_msg>awc: improve module documentation (#1656)<commit_after>#![warn(rust_2018_idioms, warnings)]
#![allow(
    clippy::type_complexity,
    clippy::borrow_interior_mutable_const,
    clippy::needless_doctest_main
)]

//! `awc` is a HTTP and WebSocket client library built using the Actix ecosystem.
//!
//! ## Making a GET request
//!
//! ```rust
//! # #[actix_rt::main]
//! # async fn main() -> Result<(), awc::error::SendRequestError> {
//! let mut client = awc::Client::default();
//! let response = client.get("http://www.rust-lang.org") // <- Create request builder
//!     .header("User-Agent", "Actix-web")
//!     .send()                                            // <- Send http request
//!     .await?;
//!
//!  println!("Response: {:?}", response);
//! # Ok(())
//! # }
//! ```
//!
//! ## Making POST requests
//!
//! ### Raw body contents
//!
//! ```rust
//! # #[actix_rt::main]
//! # async fn main() -> Result<(), awc::error::SendRequestError> {
//! let mut client = awc::Client::default();
//! let response = client.post("http://httpbin.org/post")
//!     .send_body("Raw body contents")
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ### Forms
//!
//! ```rust
//! # #[actix_rt::main]
//! # async fn main() -> Result<(), awc::error::SendRequestError> {
//! let params = [("foo", "bar"), ("baz", "quux")];
//!
//! let mut client = awc::Client::default();
//! let response = client.post("http://httpbin.org/post")
//!     .send_form(&params)
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ### JSON
//!
//! ```rust
//! # #[actix_rt::main]
//! # async fn main() -> Result<(), awc::error::SendRequestError> {
//! let request = serde_json::json!({
//!     "lang": "rust",
//!     "body": "json"
//! });
//!
//! let mut client = awc::Client::default();
//! let response = client.post("http://httpbin.org/post")
//!     .send_json(&request)
//!     .await?;
//! # Ok(())
//! # }
//! ```
//!
//! ## WebSocket support
//!
//! ```
//! # #[actix_rt::main]
//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! use futures_util::{sink::SinkExt, stream::StreamExt};
//! let (_resp, mut connection) = awc::Client::new()
//!     .ws("ws://echo.websocket.org")
//!     .connect()
//!     .await?;
//!
//! connection
//!     .send(awc::ws::Message::Text("Echo".to_string()))
//!     .await?;
//! let response = connection.next().await.unwrap()?;
//! # assert_eq!(response, awc::ws::Frame::Text("Echo".as_bytes().into()));
//! # Ok(())
//! # }
//! ```

use std::cell::RefCell;
use std::convert::TryFrom;
use std::rc::Rc;
use std::time::Duration;

pub use actix_http::{client::Connector, cookie, http};

use actix_http::http::{Error as HttpError, HeaderMap, Method, Uri};
use actix_http::RequestHead;

mod builder;
mod connect;
pub mod error;
mod frozen;
mod request;
mod response;
mod sender;
pub mod test;
pub mod ws;

pub use self::builder::ClientBuilder;
pub use self::connect::BoxedSocket;
pub use self::frozen::{FrozenClientRequest, FrozenSendBuilder};
pub use self::request::ClientRequest;
pub use self::response::{ClientResponse, JsonBody, MessageBody};
pub use self::sender::SendClientRequest;

use self::connect::{Connect, ConnectorWrapper};

/// An asynchronous HTTP and WebSocket client.
///
/// ## Examples
///
/// ```rust
/// use awc::Client;
///
/// #[actix_rt::main]
/// async fn main() {
///     let mut client = Client::default();
///
///     let res = client.get("http://www.rust-lang.org") // <- Create request builder
///         .header("User-Agent", "Actix-web")
///         .send()                             // <- Send http request
///         .await;                             // <- send request and wait for response
///
///      println!("Response: {:?}", res);
/// }
/// ```
#[derive(Clone)]
pub struct Client(Rc<ClientConfig>);

pub(crate) struct ClientConfig {
    pub(crate) connector: RefCell<Box<dyn Connect>>,
    pub(crate) headers: HeaderMap,
    pub(crate) timeout: Option<Duration>,
}

impl Default for Client {
    fn default() -> Self {
        Client(Rc::new(ClientConfig {
            connector: RefCell::new(Box::new(ConnectorWrapper(
                Connector::new().finish(),
            ))),
            headers: HeaderMap::new(),
            timeout: Some(Duration::from_secs(5)),
        }))
    }
}

impl Client {
    /// Create new client instance with default settings.
    pub fn new() -> Client {
        Client::default()
    }

    /// Build client instance.
    pub fn build() -> ClientBuilder {
        ClientBuilder::new()
    }

    /// Construct HTTP request.
    pub fn request<U>(&self, method: Method, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        let mut req = ClientRequest::new(method, url, self.0.clone());

        for (key, value) in self.0.headers.iter() {
            req = req.set_header_if_none(key.clone(), value.clone());
        }
        req
    }

    /// Create `ClientRequest` from `RequestHead`
    ///
    /// It is useful for proxy requests. This implementation
    /// copies all headers and the method.
    pub fn request_from<U>(&self, url: U, head: &RequestHead) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        let mut req = self.request(head.method.clone(), url);
        for (key, value) in head.headers.iter() {
            req = req.set_header_if_none(key.clone(), value.clone());
        }
        req
    }

    /// Construct HTTP *GET* request.
    pub fn get<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::GET, url)
    }

    /// Construct HTTP *HEAD* request.
    pub fn head<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::HEAD, url)
    }

    /// Construct HTTP *PUT* request.
    pub fn put<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::PUT, url)
    }

    /// Construct HTTP *POST* request.
    pub fn post<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::POST, url)
    }

    /// Construct HTTP *PATCH* request.
    pub fn patch<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::PATCH, url)
    }

    /// Construct HTTP *DELETE* request.
    pub fn delete<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::DELETE, url)
    }

    /// Construct HTTP *OPTIONS* request.
    pub fn options<U>(&self, url: U) -> ClientRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        self.request(Method::OPTIONS, url)
    }

    /// Initialize a WebSocket connection.
    /// Returns a WebSocket connection builder.
    pub fn ws<U>(&self, url: U) -> ws::WebsocketsRequest
    where
        Uri: TryFrom<U>,
        <Uri as TryFrom<U>>::Error: Into<HttpError>,
    {
        let mut req = ws::WebsocketsRequest::new(url, self.0.clone());
        for (key, value) in self.0.headers.iter() {
            req.head.headers.insert(key.clone(), value.clone());
        }
        req
    }
}
<|endoftext|>


<commit_before>use crate::{FullyQualifiedName, FullyQualifiedProperName, Name, PrimType, ProperName, Span, Type};
use non_empty_vec::NonEmpty;
use serde::{Deserialize, Serialize};

/// The real business value.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "expression", content = "data")]
pub enum Expression {
    /// Everyone's favourite: the humble function
    ///
    /// ```ditto
    /// (binder0, binder1) -> body
    /// ```
    Function {
        /// The source span for this expression.
        span: Span,

        /// The arguments to be bound and added to the scope of `body`.
        binders: Vec<FunctionBinder>, // REVIEW should this be a HashSet?
        // ^ NOTE we probably don't want to allow pattern matching binders in function heads
        /// The body of the function.
        body: Box<Self>,
    },
    /// A function invocation.
    ///
    /// ```ditto
    /// function(argument0, argument1)
    /// ```
    Call {
        /// The source span for this expression.
        span: Span,

        /// The return type of `function`.
        call_type: Type, // REVIEW would `function_return_type` be a better field name?

        /// The function expression to be called.
        function: Box<Self>,

        /// Arguments to pass to the function expression.
        arguments: Vec<Argument>,
    },
    /// A conditional expression.
    ///
    /// ```ditto
    /// if true then "yes" else "no!"
    /// ```
    If {
        /// The source span for this expression.
        span: Span,

        /// The output type of this conditional.
        output_type: Type,

        /// The condition.
        condition: Box<Self>,
        /// The expression to evaluate if the condition holds true.
        true_clause: Box<Self>,
        /// The expression to evaluate otherwise.
        false_clause: Box<Self>,
    },
    /// A value constructor local to the current module, e.g. `Just` and `Ok`.
    LocalConstructor {
        /// The source span for this expression.
        span: Span,

        /// The type of this constructor.
        constructor_type: Type,

        /// The constructor [ProperName].
        constructor: ProperName,
    },
    /// An imported value constructor.
    ImportedConstructor {
        /// The source span for this expression.
        span: Span,

        /// The type of this constructor.
        constructor_type: Type,

        /// The canonical constructor.
        constructor: FullyQualifiedProperName,
    },
    /// A value local to the current module, e.g. `foo`.
    LocalVariable {
        /// The source span for this expression.
        span: Span,

        /// The type of this variable.
        variable_type: Type,

        /// The variable [Name].
        variable: Name,
    },
    /// A foreign value.
    ForeignVariable {
        /// The source span for this expression.
        span: Span,
        /// The type of this variable.
        variable_type: Type,
        /// The foreign variable [Name].
        variable: Name,
    },
    /// A value that has been imported
    ImportedVariable {
        /// The source span for this expression.
        span: Span,

        /// The type of this variable.
        variable_type: Type,

        /// The canonical variable.
        variable: FullyQualifiedName,
    },
    /// A string literal.
    String {
        /// The source span for this expression.
        span: Span,
        /// `"string"`
        value: String,
    },
    /// An integer literal.
    Int {
        /// The source span for this expression.
        span: Span,
        /// `5`
        ///
        /// This value is a [String] because:
        ///
        /// 1. We want to avoid any compile-time evaluation that would result in parsing the string.
        /// For example, if the integer appears in ditto source as "005" we want to preserve that in the
        /// generated code.
        /// 2. Storing as a string avoids overflow issues.
        value: String,
    },
    /// A floating point number literal.
    Float {
        /// The source span for this expression.
        span: Span,
        /// `5.0`
        ///
        /// This value is a [String] because:
        ///
        /// 1. We want to avoid any compile-time evaluation that would result in parsing the string.
        /// For example, if the float appears in ditto source as "5.00" we want to preserve that in the
        /// generated code.
        /// 2. Storing as a string avoids float overflow and precision issues.
        value: String,
    },
    /// An array literal.
    Array {
        /// The source span for this expression.
        span: Span,
        /// The type of the elements.
        element_type: Type,
        /// Array elements.
        elements: Vec<Self>,
    },
    /// `true`
    True {
        /// The source span for this expression.
        span: Span,
    },
    /// `false`
    False {
        /// The source span for this expression.
        span: Span,
    },
    /// `unit`
    Unit {
        /// The source span for this expression.
        span: Span,
    },
    //
    // TODO GeneratedVariable? (would be used for desugaring function sections?)
}

impl Expression {
    /// Return the [Type] of this [Expression].
    pub fn get_type(&self) -> Type {
        // It'd be nice if we could call this `typeof` but that's a keyword in rust, sad face
        match self {
            Self::Call { call_type, .. } => call_type.clone(),
            Self::Function { binders, body, .. } =>
            // NOTE we derive a function type rather than storing it in a
            // `function_type` field because a) we can, and b) it removes the
            // opportunity for the derived and stored types to disagree...?
            //
            // BUT maybe we should just store it for efficiency?
            {
                Type::Function {
                    parameters: binders.iter().map(|binder| binder.get_type()).collect(),
                    return_type: Box::new(body.get_type()),
                }
            }
            Self::If { output_type, .. } => output_type.clone(),
            Self::LocalConstructor {
                constructor_type, ..
            } => constructor_type.clone(),
            Self::ImportedConstructor {
                constructor_type, ..
            } => constructor_type.clone(),
            Self::LocalVariable { variable_type, .. } => variable_type.clone(),
            Self::ForeignVariable { variable_type, .. } => variable_type.clone(),
            Self::ImportedVariable { variable_type, .. } => variable_type.clone(),
            Self::String { .. } => Type::PrimConstructor(PrimType::String),
            Self::Int { .. } => Type::PrimConstructor(PrimType::Int),
            Self::Float { .. } => Type::PrimConstructor(PrimType::Float),
            Self::Array { element_type, .. } => Type::Call {
                function: Box::new(Type::PrimConstructor(PrimType::Array)),
                arguments: NonEmpty::new(element_type.clone()),
            },
            Self::True { .. } => Type::PrimConstructor(PrimType::Bool),
            Self::False { .. } => Type::PrimConstructor(PrimType::Bool),
            Self::Unit { .. } => Type::PrimConstructor(PrimType::Unit),
        }
    }
    /// Get the source span.
    pub fn get_span(&self) -> Span {
        match self {
            Self::Function { span, .. } => *span,
            Self::Call { span, .. } => *span,
            Self::If { span, .. } => *span,
            Self::LocalConstructor { span, .. } => *span,
            Self::ImportedConstructor { span, .. } => *span,
            Self::LocalVariable { span, .. } => *span,
            Self::ForeignVariable { span, .. } => *span,
            Self::ImportedVariable { span, .. } => *span,
            Self::String { span, .. } => *span,
            Self::Int { span, .. } => *span,
            Self::Float { span, .. } => *span,
            Self::Array { span, .. } => *span,
            Self::True { span, .. } => *span,
            Self::False { span, .. } => *span,
            Self::Unit { span, .. } => *span,
        }
    }
}

/// An "argument" is passed to a function call.
///
/// ```ditto
/// some_function(argument)
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Argument {
    /// A standard expression argument.
    /// Could be a variable, could be another function call.
    Expression(Expression),
    //
    // TODO sections, e.g. `some_function(&1, True, &2, 5)`
}

impl Argument {
    /// Return the [Type] of this [Argument].
    pub fn get_type(&self) -> Type {
        match self {
            Self::Expression(expression) => expression.get_type(),
        }
    }
    /// Return the source [Span] for this [Argument].
    pub fn get_span(&self) -> Span {
        match self {
            Self::Expression(expression) => expression.get_span(),
        }
    }
}

/// Binds a variable as part of a function header.
///
/// After (successful) type-checking we should know the type of all binders,
/// hence all variants mention a [Type].
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FunctionBinder {
    /// A standard name binder.
    Name {
        /// The source span for this binder.
        span: Span,
        /// The type of this binder.
        binder_type: Type,
        /// The name being bound.
        value: Name,
    },
}

impl FunctionBinder {
    /// Return the [Type] of this [FunctionBinder].
    pub fn get_type(&self) -> Type {
        match self {
            Self::Name { binder_type, .. } => binder_type.clone(),
        }
    }
    /// Return the source [Span] for this [FunctionBinder].
    pub fn get_span(&self) -> Span {
        match self {
            Self::Name { span, .. } => *span,
        }
    }
}
<commit_msg>Add match expressions to the AST<commit_after>use crate::{FullyQualifiedName, FullyQualifiedProperName, Name, PrimType, ProperName, Span, Type};
use non_empty_vec::NonEmpty;
use serde::{Deserialize, Serialize};

/// The real business value.
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "expression", content = "data")]
pub enum Expression {
    /// Everyone's favourite: the humble function
    ///
    /// ```ditto
    /// (binder0, binder1) -> body
    /// ```
    Function {
        /// The source span for this expression.
        span: Span,

        /// The arguments to be bound and added to the scope of `body`.
        binders: Vec<FunctionBinder>, // REVIEW should this be a HashSet?
        // ^ NOTE we probably don't want to allow pattern matching binders in function heads
        /// The body of the function.
        body: Box<Self>,
    },
    /// A function invocation.
    ///
    /// ```ditto
    /// function(argument0, argument1)
    /// ```
    Call {
        /// The source span for this expression.
        span: Span,

        /// The return type of `function`.
        call_type: Type, // REVIEW would `function_return_type` be a better field name?

        /// The function expression to be called.
        function: Box<Self>,

        /// Arguments to pass to the function expression.
        arguments: Vec<Argument>,
    },
    /// A conditional expression.
    ///
    /// ```ditto
    /// if true then "yes" else "no!"
    /// ```
    If {
        /// The source span for this expression.
        span: Span,

        /// The output type of this conditional.
        output_type: Type,

        /// The condition.
        condition: Box<Self>,
        /// The expression to evaluate if the condition holds true.
        true_clause: Box<Self>,
        /// The expression to evaluate otherwise.
        false_clause: Box<Self>,
    },
    /// A pattern match.
    ///
    /// ```ditto
    /// match some_expr with
    /// | Pattern -> another_expr
    /// ```
    Match {
        /// The source span for this expression.
        span: Span,

        /// The type of the expressions in the `arms`.
        match_type: Type,

        /// Expression to be matched.
        expression: Box<Self>,

        /// Patterns to be matched against and their corresponding expressions.
        arms: NonEmpty<(Pattern, Self)>,
    },
    /// A value constructor local to the current module, e.g. `Just` and `Ok`.
    LocalConstructor {
        /// The source span for this expression.
        span: Span,

        /// The type of this constructor.
        constructor_type: Type,

        /// The constructor [ProperName].
        constructor: ProperName,
    },
    /// An imported value constructor.
    ImportedConstructor {
        /// The source span for this expression.
        span: Span,

        /// The type of this constructor.
        constructor_type: Type,

        /// The canonical constructor.
        constructor: FullyQualifiedProperName,
    },
    /// A value local to the current module, e.g. `foo`.
    LocalVariable {
        /// The source span for this expression.
        span: Span,

        /// The type of this variable.
        variable_type: Type,

        /// The variable [Name].
        variable: Name,
    },
    /// A foreign value.
    ForeignVariable {
        /// The source span for this expression.
        span: Span,
        /// The type of this variable.
        variable_type: Type,
        /// The foreign variable [Name].
        variable: Name,
    },
    /// A value that has been imported
    ImportedVariable {
        /// The source span for this expression.
        span: Span,

        /// The type of this variable.
        variable_type: Type,

        /// The canonical variable.
        variable: FullyQualifiedName,
    },
    /// A string literal.
    String {
        /// The source span for this expression.
        span: Span,
        /// `"string"`
        value: String,
    },
    /// An integer literal.
    Int {
        /// The source span for this expression.
        span: Span,
        /// `5`
        ///
        /// This value is a [String] because:
        ///
        /// 1. We want to avoid any compile-time evaluation that would result in parsing the string.
        /// For example, if the integer appears in ditto source as "005" we want to preserve that in the
        /// generated code.
        /// 2. Storing as a string avoids overflow issues.
        value: String,
    },
    /// A floating point number literal.
    Float {
        /// The source span for this expression.
        span: Span,
        /// `5.0`
        ///
        /// This value is a [String] because:
        ///
        /// 1. We want to avoid any compile-time evaluation that would result in parsing the string.
        /// For example, if the float appears in ditto source as "5.00" we want to preserve that in the
        /// generated code.
        /// 2. Storing as a string avoids float overflow and precision issues.
        value: String,
    },
    /// An array literal.
    Array {
        /// The source span for this expression.
        span: Span,
        /// The type of the elements.
        element_type: Type,
        /// Array elements.
        elements: Vec<Self>,
    },
    /// `true`
    True {
        /// The source span for this expression.
        span: Span,
    },
    /// `false`
    False {
        /// The source span for this expression.
        span: Span,
    },
    /// `unit`
    Unit {
        /// The source span for this expression.
        span: Span,
    },
    //
    // TODO GeneratedVariable? (would be used for desugaring function sections?)
}

impl Expression {
    /// Return the [Type] of this [Expression].
    pub fn get_type(&self) -> Type {
        // It'd be nice if we could call this `typeof` but that's a keyword in rust, sad face
        match self {
            Self::Call { call_type, .. } => call_type.clone(),
            Self::Function { binders, body, .. } =>
            // NOTE we derive a function type rather than storing it in a
            // `function_type` field because a) we can, and b) it removes the
            // opportunity for the derived and stored types to disagree...?
            //
            // BUT maybe we should just store it for efficiency?
            {
                Type::Function {
                    parameters: binders.iter().map(|binder| binder.get_type()).collect(),
                    return_type: Box::new(body.get_type()),
                }
            }
            Self::If { output_type, .. } => output_type.clone(),
            Self::Match { match_type, .. } => match_type.clone(),
            Self::LocalConstructor {
                constructor_type, ..
            } => constructor_type.clone(),
            Self::ImportedConstructor {
                constructor_type, ..
            } => constructor_type.clone(),
            Self::LocalVariable { variable_type, .. } => variable_type.clone(),
            Self::ForeignVariable { variable_type, .. } => variable_type.clone(),
            Self::ImportedVariable { variable_type, .. } => variable_type.clone(),
            Self::String { .. } => Type::PrimConstructor(PrimType::String),
            Self::Int { .. } => Type::PrimConstructor(PrimType::Int),
            Self::Float { .. } => Type::PrimConstructor(PrimType::Float),
            Self::Array { element_type, .. } => Type::Call {
                function: Box::new(Type::PrimConstructor(PrimType::Array)),
                arguments: NonEmpty::new(element_type.clone()),
            },
            Self::True { .. } => Type::PrimConstructor(PrimType::Bool),
            Self::False { .. } => Type::PrimConstructor(PrimType::Bool),
            Self::Unit { .. } => Type::PrimConstructor(PrimType::Unit),
        }
    }
    /// Get the source span.
    pub fn get_span(&self) -> Span {
        match self {
            Self::Function { span, .. } => *span,
            Self::Call { span, .. } => *span,
            Self::If { span, .. } => *span,
            Self::Match { span, .. } => *span,
            Self::LocalConstructor { span, .. } => *span,
            Self::ImportedConstructor { span, .. } => *span,
            Self::LocalVariable { span, .. } => *span,
            Self::ForeignVariable { span, .. } => *span,
            Self::ImportedVariable { span, .. } => *span,
            Self::String { span, .. } => *span,
            Self::Int { span, .. } => *span,
            Self::Float { span, .. } => *span,
            Self::Array { span, .. } => *span,
            Self::True { span, .. } => *span,
            Self::False { span, .. } => *span,
            Self::Unit { span, .. } => *span,
        }
    }
}

/// An "argument" is passed to a function call.
///
/// ```ditto
/// some_function(argument)
/// ```
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Argument {
    /// A standard expression argument.
    /// Could be a variable, could be another function call.
    Expression(Expression),
    //
    // TODO sections, e.g. `some_function(&1, True, &2, 5)`
}

impl Argument {
    /// Return the [Type] of this [Argument].
    pub fn get_type(&self) -> Type {
        match self {
            Self::Expression(expression) => expression.get_type(),
        }
    }
    /// Return the source [Span] for this [Argument].
    pub fn get_span(&self) -> Span {
        match self {
            Self::Expression(expression) => expression.get_span(),
        }
    }
}

/// Binds a variable as part of a function header.
///
/// After (successful) type-checking we should know the type of all binders,
/// hence all variants mention a [Type].
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum FunctionBinder {
    /// A standard name binder.
    Name {
        /// The source span for this binder.
        span: Span,
        /// The type of this binder.
        binder_type: Type,
        /// The name being bound.
        value: Name,
    },
}

impl FunctionBinder {
    /// Return the [Type] of this [FunctionBinder].
    pub fn get_type(&self) -> Type {
        match self {
            Self::Name { binder_type, .. } => binder_type.clone(),
        }
    }
    /// Return the source [Span] for this [FunctionBinder].
    pub fn get_span(&self) -> Span {
        match self {
            Self::Name { span, .. } => *span,
        }
    }
}

/// A pattern to be matched.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Pattern {
    /// A local constructor pattern.
    LocalConstructor {
        /// The source span for this pattern.
        span: Span,
        /// `Just`
        constructor: ProperName,
        /// Pattern arguments to the constructor.
        arguments: Vec<Self>,
    },
    /// An importedf constructor pattern.
    ImportedConstructor {
        /// The source span for this pattern.
        span: Span,
        /// `Maybe.Just`
        constructor: FullyQualifiedProperName,
        /// Pattern arguments to the constructor.
        arguments: Vec<Self>,
    },
    /// A variable binding pattern.
    Variable {
        /// The source span for this pattern.
        span: Span,
        /// Name to bind.
        name: Name,
    },
}
<|endoftext|>


<commit_before>use SyntaxNodeRef;

pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeRef<'a>> {
    walk(root).filter_map(|event| match event {
        WalkEvent::Enter(node) => Some(node),
        WalkEvent::Exit(_) => None,
    })
}

#[derive(Debug, Copy, Clone)]
pub enum WalkEvent<'a> {
    Enter(SyntaxNodeRef<'a>),
    Exit(SyntaxNodeRef<'a>),
}

pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> {
    let mut done = false;
    ::itertools::unfold(WalkEvent::Enter(root), move |pos| {
        if done {
            return None;
        }
        let res = *pos;
        *pos = match *pos {
            WalkEvent::Enter(node) => match node.first_child() {
                Some(child) => WalkEvent::Enter(child),
                None => WalkEvent::Exit(node),
            },
            WalkEvent::Exit(node) => {
                if node == root {
                    done = true;
                    WalkEvent::Exit(node)
                } else {
                    match node.next_sibling() {
                        Some(sibling) => WalkEvent::Enter(sibling),
                        None => match node.parent() {
                            Some(node) => WalkEvent::Exit(node),
                            None => WalkEvent::Exit(node),
                        },
                    }
                }
            }
        };
        Some(res)
    })
}
<commit_msg>Simplify walk<commit_after>use {
    SyntaxNodeRef,
    algo::generate,
};

pub fn preorder<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = SyntaxNodeRef<'a>> {
    walk(root).filter_map(|event| match event {
        WalkEvent::Enter(node) => Some(node),
        WalkEvent::Exit(_) => None,
    })
}

#[derive(Debug, Copy, Clone)]
pub enum WalkEvent<'a> {
    Enter(SyntaxNodeRef<'a>),
    Exit(SyntaxNodeRef<'a>),
}

pub fn walk<'a>(root: SyntaxNodeRef<'a>) -> impl Iterator<Item = WalkEvent<'a>> {
    generate(Some(WalkEvent::Enter(root)), |pos| {
        let next = match *pos {
            WalkEvent::Enter(node) => match node.first_child() {
                Some(child) => WalkEvent::Enter(child),
                None => WalkEvent::Exit(node),
            },
            WalkEvent::Exit(node) => {
                match node.next_sibling() {
                    Some(sibling) => WalkEvent::Enter(sibling),
                    None => match node.parent() {
                        Some(node) => WalkEvent::Exit(node),
                        None => return None,
                    },
                }
            }
        };
        Some(next)
    })
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

use ra_db::SourceDatabase;
use ra_syntax::{
    algo::find_node_at_offset,
    ast::{self, ArgListOwner},
    AstNode, SyntaxNode, TextUnit,
};
use test_utils::tested_by;

use crate::{db::RootDatabase, CallInfo, FilePosition, FunctionSignature};

/// Computes parameter information for the given call expression.
pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
    let parse = db.parse(position.file_id);
    let syntax = parse.tree().syntax().clone();

    // Find the calling expression and it's NameRef
    let calling_node = FnCallNode::with_node(&syntax, position.offset)?;
    let name_ref = calling_node.name_ref()?;

    let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
    let function = match &calling_node {
        FnCallNode::CallExpr(expr) => {
            //FIXME: apply subst
            let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
            match callable_def {
                hir::CallableDef::Function(it) => it,
                //FIXME: handle other callables
                _ => return None,
            }
        }
        FnCallNode::MethodCallExpr(expr) => analyzer.resolve_method_call(&expr)?,
    };

    let mut call_info = CallInfo::new(db, function);

    // If we have a calling expression let's find which argument we are on
    let num_params = call_info.parameters().len();
    let has_self = function.data(db).has_self_param();

    if num_params == 1 {
        if !has_self {
            call_info.active_parameter = Some(0);
        }
    } else if num_params > 1 {
        // Count how many parameters into the call we are.
        if let Some(arg_list) = calling_node.arg_list() {
            // Number of arguments specified at the call site
            let num_args_at_callsite = arg_list.args().count();

            let arg_list_range = arg_list.syntax().text_range();
            if !arg_list_range.contains_inclusive(position.offset) {
                tested_by!(call_info_bad_offset);
                return None;
            }

            let mut param = std::cmp::min(
                num_args_at_callsite,
                arg_list
                    .args()
                    .take_while(|arg| arg.syntax().text_range().end() < position.offset)
                    .count(),
            );

            // If we are in a method account for `self`
            if has_self {
                param += 1;
            }

            call_info.active_parameter = Some(param);
        }
    }

    Some(call_info)
}

enum FnCallNode {
    CallExpr(ast::CallExpr),
    MethodCallExpr(ast::MethodCallExpr),
}

impl FnCallNode {
    fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option<FnCallNode> {
        if let Some(expr) = find_node_at_offset::<ast::CallExpr>(syntax, offset) {
            return Some(FnCallNode::CallExpr(expr));
        }
        if let Some(expr) = find_node_at_offset::<ast::MethodCallExpr>(syntax, offset) {
            return Some(FnCallNode::MethodCallExpr(expr));
        }
        None
    }

    fn name_ref(&self) -> Option<ast::NameRef> {
        match self {
            FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? {
                ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
                _ => return None,
            }),

            FnCallNode::MethodCallExpr(call_expr) => {
                call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
            }
        }
    }

    fn arg_list(&self) -> Option<ast::ArgList> {
        match self {
            FnCallNode::CallExpr(expr) => expr.arg_list(),
            FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
        }
    }
}

impl CallInfo {
    fn new(db: &RootDatabase, function: hir::Function) -> Self {
        let signature = FunctionSignature::from_hir(db, function);

        CallInfo { signature, active_parameter: None }
    }

    fn parameters(&self) -> &[String] {
        &self.signature.parameters
    }
}

#[cfg(test)]
mod tests {
    use test_utils::covers;

    use crate::mock_analysis::single_file_with_position;

    use super::*;

    // These are only used when testing
    impl CallInfo {
        fn doc(&self) -> Option<hir::Documentation> {
            self.signature.doc.clone()
        }

        fn label(&self) -> String {
            self.signature.to_string()
        }
    }

    fn call_info(text: &str) -> CallInfo {
        let (analysis, position) = single_file_with_position(text);
        analysis.call_info(position).unwrap().unwrap()
    }

    #[test]
    fn test_fn_signature_two_args_firstx() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>3, ); }"#,
        );

        assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_two_args_second() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(3, <|>); }"#,
        );

        assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_two_args_empty() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>); }"#,
        );

        assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_two_args_first_generics() {
        let info = call_info(
            r#"fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 where T: Copy + Display, U: Debug {x + y}
fn bar() { foo(<|>3, ); }"#,
        );

        assert_eq!(info.parameters(), ["x: T", "y: U"]);
        assert_eq!(
            info.label(),
            r#"
fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
where T: Copy + Display,
      U: Debug
    "#
            .trim()
        );
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_no_params() {
        let info = call_info(
            r#"fn foo<T>() -> T where T: Copy + Display {}
fn bar() { foo(<|>); }"#,
        );

        assert!(info.parameters().is_empty());
        assert_eq!(
            info.label(),
            r#"
fn foo<T>() -> T
where T: Copy + Display
    "#
            .trim()
        );
        assert!(info.active_parameter.is_none());
    }

    #[test]
    fn test_fn_signature_for_impl() {
        let info = call_info(
            r#"struct F; impl F { pub fn new() { F{}} }
fn bar() {let _ : F = F::new(<|>);}"#,
        );

        assert!(info.parameters().is_empty());
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_self() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters(), ["&self"]);
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_with_arg() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self, x: i32) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters(), ["&self", "x: i32"]);
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_with_docs_simple() {
        let info = call_info(
            r#"
/// test
// non-doc-comment
fn foo(j: u32) -> u32 {
    j
}

fn bar() {
    let _ = foo(<|>);
}
"#,
        );

        assert_eq!(info.parameters(), ["j: u32"]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label(), "fn foo(j: u32) -> u32");
        assert_eq!(info.doc().map(|it| it.into()), Some("test".to_string()));
    }

    #[test]
    fn test_fn_signature_with_docs() {
        let info = call_info(
            r#"
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}

pub fn do() {
    add_one(<|>
}"#,
        );

        assert_eq!(info.parameters(), ["x: i32"]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
        assert_eq!(
            info.doc().map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_impl() {
        let info = call_info(
            r#"
struct addr;
impl addr {
    /// Adds one to the number given.
    ///
    /// # Examples
    ///
    /// ```
    /// let five = 5;
    ///
    /// assert_eq!(6, my_crate::add_one(5));
    /// ```
    pub fn add_one(x: i32) -> i32 {
        x + 1
    }
}

pub fn do_it() {
    addr {};
    addr::add_one(<|>);
}"#,
        );

        assert_eq!(info.parameters(), ["x: i32"]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
        assert_eq!(
            info.doc().map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_from_actix() {
        let info = call_info(
            r#"
struct WriteHandler<E>;

impl<E> WriteHandler<E> {
    /// Method is called when writer emits error.
    ///
    /// If this method returns `ErrorAction::Continue` writer processing
    /// continues otherwise stream processing stops.
    fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running {
        Running::Stop
    }

    /// Method is called when writer finishes.
    ///
    /// By default this method stops actor's `Context`.
    fn finished(&mut self, ctx: &mut Self::Context) {
        ctx.stop()
    }
}

pub fn foo(mut r: WriteHandler<()>) {
    r.finished(<|>);
}

"#,
        );

        assert_eq!(info.parameters(), ["&mut self", "ctx: &mut Self::Context"]);
        assert_eq!(info.active_parameter, Some(1));
        assert_eq!(
            info.doc().map(|it| it.into()),
            Some(
                r#"Method is called when writer finishes.

By default this method stops actor's `Context`."#
                    .to_string()
            )
        );
    }

    #[test]
    fn call_info_bad_offset() {
        covers!(call_info_bad_offset);
        let (analysis, position) = single_file_with_position(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
               fn bar() { foo <|> (3, ); }"#,
        );
        let call_info = analysis.call_info(position).unwrap();
        assert!(call_info.is_none());
    }
}
<commit_msg>Be more precise with function signatures<commit_after>//! FIXME: write short doc here

use ra_db::SourceDatabase;
use ra_syntax::{
    algo::ancestors_at_offset,
    ast::{self, ArgListOwner},
    AstNode, SyntaxNode, TextUnit,
};
use test_utils::tested_by;

use crate::{db::RootDatabase, CallInfo, FilePosition, FunctionSignature};

/// Computes parameter information for the given call expression.
pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<CallInfo> {
    let parse = db.parse(position.file_id);
    let syntax = parse.tree().syntax().clone();

    // Find the calling expression and it's NameRef
    let calling_node = FnCallNode::with_node(&syntax, position.offset)?;
    let name_ref = calling_node.name_ref()?;

    let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
    let function = match &calling_node {
        FnCallNode::CallExpr(expr) => {
            //FIXME: apply subst
            let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?;
            match callable_def {
                hir::CallableDef::Function(it) => it,
                //FIXME: handle other callables
                _ => return None,
            }
        }
        FnCallNode::MethodCallExpr(expr) => analyzer.resolve_method_call(&expr)?,
    };

    let mut call_info = CallInfo::new(db, function);

    // If we have a calling expression let's find which argument we are on
    let num_params = call_info.parameters().len();
    let has_self = function.data(db).has_self_param();

    if num_params == 1 {
        if !has_self {
            call_info.active_parameter = Some(0);
        }
    } else if num_params > 1 {
        // Count how many parameters into the call we are.
        if let Some(arg_list) = calling_node.arg_list() {
            // Number of arguments specified at the call site
            let num_args_at_callsite = arg_list.args().count();

            let arg_list_range = arg_list.syntax().text_range();
            if !arg_list_range.contains_inclusive(position.offset) {
                tested_by!(call_info_bad_offset);
                return None;
            }

            let mut param = std::cmp::min(
                num_args_at_callsite,
                arg_list
                    .args()
                    .take_while(|arg| arg.syntax().text_range().end() < position.offset)
                    .count(),
            );

            // If we are in a method account for `self`
            if has_self {
                param += 1;
            }

            call_info.active_parameter = Some(param);
        }
    }

    Some(call_info)
}

enum FnCallNode {
    CallExpr(ast::CallExpr),
    MethodCallExpr(ast::MethodCallExpr),
}

impl FnCallNode {
    fn with_node(syntax: &SyntaxNode, offset: TextUnit) -> Option<FnCallNode> {
        ancestors_at_offset(syntax, offset).find_map(|node| {
            if let Some(expr) = ast::CallExpr::cast(node.clone()) {
                Some(FnCallNode::CallExpr(expr))
            } else if let Some(expr) = ast::MethodCallExpr::cast(node.clone()) {
                Some(FnCallNode::MethodCallExpr(expr))
            } else {
                None
            }
        })
    }

    fn name_ref(&self) -> Option<ast::NameRef> {
        match self {
            FnCallNode::CallExpr(call_expr) => Some(match call_expr.expr()? {
                ast::Expr::PathExpr(path_expr) => path_expr.path()?.segment()?.name_ref()?,
                _ => return None,
            }),

            FnCallNode::MethodCallExpr(call_expr) => {
                call_expr.syntax().children().filter_map(ast::NameRef::cast).nth(0)
            }
        }
    }

    fn arg_list(&self) -> Option<ast::ArgList> {
        match self {
            FnCallNode::CallExpr(expr) => expr.arg_list(),
            FnCallNode::MethodCallExpr(expr) => expr.arg_list(),
        }
    }
}

impl CallInfo {
    fn new(db: &RootDatabase, function: hir::Function) -> Self {
        let signature = FunctionSignature::from_hir(db, function);

        CallInfo { signature, active_parameter: None }
    }

    fn parameters(&self) -> &[String] {
        &self.signature.parameters
    }
}

#[cfg(test)]
mod tests {
    use test_utils::covers;

    use crate::mock_analysis::single_file_with_position;

    use super::*;

    // These are only used when testing
    impl CallInfo {
        fn doc(&self) -> Option<hir::Documentation> {
            self.signature.doc.clone()
        }

        fn label(&self) -> String {
            self.signature.to_string()
        }
    }

    fn call_info(text: &str) -> CallInfo {
        let (analysis, position) = single_file_with_position(text);
        analysis.call_info(position).unwrap().unwrap()
    }

    #[test]
    fn test_fn_signature_two_args_firstx() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>3, ); }"#,
        );

        assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_two_args_second() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(3, <|>); }"#,
        );

        assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_two_args_empty() {
        let info = call_info(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
fn bar() { foo(<|>); }"#,
        );

        assert_eq!(info.parameters(), ["x: u32", "y: u32"]);
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_two_args_first_generics() {
        let info = call_info(
            r#"fn foo<T, U: Copy + Display>(x: T, y: U) -> u32 where T: Copy + Display, U: Debug {x + y}
fn bar() { foo(<|>3, ); }"#,
        );

        assert_eq!(info.parameters(), ["x: T", "y: U"]);
        assert_eq!(
            info.label(),
            r#"
fn foo<T, U: Copy + Display>(x: T, y: U) -> u32
where T: Copy + Display,
      U: Debug
    "#
            .trim()
        );
        assert_eq!(info.active_parameter, Some(0));
    }

    #[test]
    fn test_fn_signature_no_params() {
        let info = call_info(
            r#"fn foo<T>() -> T where T: Copy + Display {}
fn bar() { foo(<|>); }"#,
        );

        assert!(info.parameters().is_empty());
        assert_eq!(
            info.label(),
            r#"
fn foo<T>() -> T
where T: Copy + Display
    "#
            .trim()
        );
        assert!(info.active_parameter.is_none());
    }

    #[test]
    fn test_fn_signature_for_impl() {
        let info = call_info(
            r#"struct F; impl F { pub fn new() { F{}} }
fn bar() {let _ : F = F::new(<|>);}"#,
        );

        assert!(info.parameters().is_empty());
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_self() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters(), ["&self"]);
        assert_eq!(info.active_parameter, None);
    }

    #[test]
    fn test_fn_signature_for_method_with_arg() {
        let info = call_info(
            r#"struct F;
impl F {
    pub fn new() -> F{
        F{}
    }

    pub fn do_it(&self, x: i32) {}
}

fn bar() {
    let f : F = F::new();
    f.do_it(<|>);
}"#,
        );

        assert_eq!(info.parameters(), ["&self", "x: i32"]);
        assert_eq!(info.active_parameter, Some(1));
    }

    #[test]
    fn test_fn_signature_with_docs_simple() {
        let info = call_info(
            r#"
/// test
// non-doc-comment
fn foo(j: u32) -> u32 {
    j
}

fn bar() {
    let _ = foo(<|>);
}
"#,
        );

        assert_eq!(info.parameters(), ["j: u32"]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label(), "fn foo(j: u32) -> u32");
        assert_eq!(info.doc().map(|it| it.into()), Some("test".to_string()));
    }

    #[test]
    fn test_fn_signature_with_docs() {
        let info = call_info(
            r#"
/// Adds one to the number given.
///
/// # Examples
///
/// ```
/// let five = 5;
///
/// assert_eq!(6, my_crate::add_one(5));
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}

pub fn do() {
    add_one(<|>
}"#,
        );

        assert_eq!(info.parameters(), ["x: i32"]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
        assert_eq!(
            info.doc().map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_impl() {
        let info = call_info(
            r#"
struct addr;
impl addr {
    /// Adds one to the number given.
    ///
    /// # Examples
    ///
    /// ```
    /// let five = 5;
    ///
    /// assert_eq!(6, my_crate::add_one(5));
    /// ```
    pub fn add_one(x: i32) -> i32 {
        x + 1
    }
}

pub fn do_it() {
    addr {};
    addr::add_one(<|>);
}"#,
        );

        assert_eq!(info.parameters(), ["x: i32"]);
        assert_eq!(info.active_parameter, Some(0));
        assert_eq!(info.label(), "pub fn add_one(x: i32) -> i32");
        assert_eq!(
            info.doc().map(|it| it.into()),
            Some(
                r#"Adds one to the number given.

# Examples

```
let five = 5;

assert_eq!(6, my_crate::add_one(5));
```"#
                    .to_string()
            )
        );
    }

    #[test]
    fn test_fn_signature_with_docs_from_actix() {
        let info = call_info(
            r#"
struct WriteHandler<E>;

impl<E> WriteHandler<E> {
    /// Method is called when writer emits error.
    ///
    /// If this method returns `ErrorAction::Continue` writer processing
    /// continues otherwise stream processing stops.
    fn error(&mut self, err: E, ctx: &mut Self::Context) -> Running {
        Running::Stop
    }

    /// Method is called when writer finishes.
    ///
    /// By default this method stops actor's `Context`.
    fn finished(&mut self, ctx: &mut Self::Context) {
        ctx.stop()
    }
}

pub fn foo(mut r: WriteHandler<()>) {
    r.finished(<|>);
}

"#,
        );

        assert_eq!(info.parameters(), ["&mut self", "ctx: &mut Self::Context"]);
        assert_eq!(info.active_parameter, Some(1));
        assert_eq!(
            info.doc().map(|it| it.into()),
            Some(
                r#"Method is called when writer finishes.

By default this method stops actor's `Context`."#
                    .to_string()
            )
        );
    }

    #[test]
    fn call_info_bad_offset() {
        covers!(call_info_bad_offset);
        let (analysis, position) = single_file_with_position(
            r#"fn foo(x: u32, y: u32) -> u32 {x + y}
               fn bar() { foo <|> (3, ); }"#,
        );
        let call_info = analysis.call_info(position).unwrap();
        assert!(call_info.is_none());
    }

    #[test]
    fn test_nested_method_in_lamba() {
        let info = call_info(
            r#"struct Foo;

impl Foo {
    fn bar(&self, _: u32) { }
}

fn bar(_: u32) { }

fn main() {
    let foo = Foo;
    std::thread::spawn(move || foo.bar(<|>));
}"#,
        );

        assert_eq!(info.parameters(), ["&self", "_: u32"]);
        assert_eq!(info.active_parameter, Some(1));
        assert_eq!(info.label(), "fn bar(&self, _: u32)");
    }
}
<|endoftext|>


<commit_before>#![cfg(feature = "mp4")]
#[macro_use]
extern crate criterion;

extern crate byteorder;
extern crate combine;

use std::{fs::File, io::Read, str::from_utf8};

use {
    byteorder::{BigEndian, ByteOrder},
    combine::{
        parser::range::{range, take},
        stream::easy::ParseError,
        *,
    },
    criterion::{black_box, Bencher, Criterion},
};

#[derive(Clone, PartialEq, Eq, Debug)]
struct FileType<'a> {
    major_brand: &'a str,
    major_brand_version: &'a [u8],
    compatible_brands: Vec<&'a str>,
}

#[derive(Clone, Debug)]
enum MP4Box<'a> {
    Ftyp(FileType<'a>),
    Moov,
    Mdat,
    Free,
    Skip,
    Wide,
    Unknown,
}

fn parse_mp4(data: &[u8]) -> Result<(Vec<MP4Box>, &[u8]), ParseError<&[u8]>> {
    let brand_name = || take(4).and_then(from_utf8);
    let filetype_box = (
        range(&b"ftyp"[..]),
        brand_name(),
        take(4),
        many(brand_name()),
    )
        .map(|(_, m, v, c)| {
            MP4Box::Ftyp(FileType {
                major_brand: m,
                major_brand_version: v,
                compatible_brands: c,
            })
        });

    let mp4_box = take(4)
        .map(BigEndian::read_u32)
        .then(|offset| take(offset as usize - 4));
    let mut box_parser = choice((
        filetype_box,
        range(&b"moov"[..]).map(|_| MP4Box::Moov),
        range(&b"mdat"[..]).map(|_| MP4Box::Mdat),
        range(&b"free"[..]).map(|_| MP4Box::Free),
        range(&b"skip"[..]).map(|_| MP4Box::Skip),
        range(&b"wide"[..]).map(|_| MP4Box::Wide),
        value(MP4Box::Unknown),
    ));
    let data_interpreter =
        mp4_box.flat_map(|box_data| box_parser.easy_parse(box_data).map(|t| t.0));

    many(data_interpreter).easy_parse(data)
}

fn run_test(b: &mut Bencher, data: &[u8]) {
    b.iter(|| match parse_mp4(data) {
        Ok(x) => black_box(x),
        Err(err) => panic!("{}", err.map_range(|bytes| format!("{:?}", bytes))),
    });
}

fn mp4_small_test(c: &mut Criterion) {
    let mut mp4_small = Vec::new();
    File::open("benches/small.mp4")
        .and_then(|mut f| f.read_to_end(&mut mp4_small))
        .expect("Unable to read benches/small.mp4");

    c.bench_function("mp4_small", move |b| run_test(b, &mp4_small));
}

criterion_group!(mp4, mp4_small_test);
criterion_main!(mp4);
<commit_msg>Fix mp4 bench<commit_after>#![cfg(feature = "mp4")]
#[macro_use]
extern crate criterion;

use std::{fs::File, io::Read, str::from_utf8};

use {
    combine::{
        parser::{
            byte::num::be_u32,
            range::{range, take},
        },
        stream::easy::ParseError,
        *,
    },
    criterion::{black_box, Bencher, Criterion},
};

#[derive(Clone, PartialEq, Eq, Debug)]
struct FileType<'a> {
    major_brand: &'a str,
    major_brand_version: &'a [u8],
    compatible_brands: Vec<&'a str>,
}

#[derive(Clone, Debug)]
enum MP4Box<'a> {
    Ftyp(FileType<'a>),
    Moov,
    Mdat,
    Free,
    Skip,
    Wide,
    Unknown,
}

fn parse_mp4(data: &[u8]) -> Result<(Vec<MP4Box>, &[u8]), ParseError<&[u8]>> {
    let brand_name = || take(4).and_then(from_utf8);
    let filetype_box = (
        range(&b"ftyp"[..]),
        brand_name(),
        take(4),
        many(brand_name()),
    )
        .map(|(_, m, v, c)| {
            MP4Box::Ftyp(FileType {
                major_brand: m,
                major_brand_version: v,
                compatible_brands: c,
            })
        });

    let mp4_box = be_u32().then(|offset| take(offset as usize - 4));
    let mut box_parser = choice((
        filetype_box,
        range(&b"moov"[..]).map(|_| MP4Box::Moov),
        range(&b"mdat"[..]).map(|_| MP4Box::Mdat),
        range(&b"free"[..]).map(|_| MP4Box::Free),
        range(&b"skip"[..]).map(|_| MP4Box::Skip),
        range(&b"wide"[..]).map(|_| MP4Box::Wide),
        value(MP4Box::Unknown),
    ));
    let data_interpreter =
        mp4_box.flat_map(|box_data| box_parser.easy_parse(box_data).map(|t| t.0));

    many(data_interpreter).easy_parse(data)
}

fn run_test(b: &mut Bencher, data: &[u8]) {
    b.iter(|| match parse_mp4(data) {
        Ok(x) => black_box(x),
        Err(err) => panic!("{}", err.map_range(|bytes| format!("{:?}", bytes))),
    });
}

fn mp4_small_test(c: &mut Criterion) {
    let mut mp4_small = Vec::new();
    File::open("benches/small.mp4")
        .and_then(|mut f| f.read_to_end(&mut mp4_small))
        .expect("Unable to read benches/small.mp4");

    c.bench_function("mp4_small", move |b| run_test(b, &mp4_small));
}

criterion_group!(mp4, mp4_small_test);
criterion_main!(mp4);
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Supports dynamic assertions in about what sort of thread is running and
//! what state it's in.

#![deny(missing_docs)]

pub use self::imp::{enter, exit, get, initialize};

bitflags! {
    /// A thread state flag, used for multiple assertions.
    pub flags ThreadState: u32 {
        /// Whether we're in a script thread.
        const SCRIPT          = 0x01,
        /// Whether we're in a layout thread.
        const LAYOUT          = 0x02,

        /// Whether we're in a script worker thread (actual web workers), or in
        /// a layout worker thread.
        const IN_WORKER       = 0x0100,

        /// Whether the current thread is going through a GC.
        const IN_GC           = 0x0200,
    }
}

macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
    impl ThreadState {
        /// Whether the current thread is a worker thread.
        pub fn is_worker(self) -> bool {
            self.contains(IN_WORKER)
        }

        $(
            #[allow(missing_docs)]
            pub fn $fun(self) -> bool {
                self.contains($flag)
            }
        )*
    }

    static TYPES: &'static [ThreadState] =
        &[ $( $flag ),* ];
));

thread_types! {
    is_script = SCRIPT;
    is_layout = LAYOUT;
}

mod imp {
    use std::cell::RefCell;
    use super::{TYPES, ThreadState};

    thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));

    /// Initialize the current thread state.
    pub fn initialize(x: ThreadState) {
        STATE.with(|ref k| {
            if let Some(ref s) = *k.borrow() {
                panic!("Thread state already initialized as {:?}", s);
            }
            *k.borrow_mut() = Some(x);
        });
        get(); // check the assertion below
    }

    /// Get the current thread state.
    pub fn get() -> ThreadState {
        let state = STATE.with(|ref k| {
            match *k.borrow() {
                // This is one of the layout threads, that use rayon.
                None => super::LAYOUT | super::IN_WORKER,
                Some(s) => s,
            }
        });

        // Exactly one of the thread type flags should be set.
        debug_assert_eq!(1, TYPES.iter().filter(|&&ty| state.contains(ty)).count());
        state
    }

    /// Enter into a given temporary state. Panics if re-entring.
    pub fn enter(x: ThreadState) {
        let state = get();
        debug_assert!(!state.intersects(x));
        STATE.with(|ref k| {
            *k.borrow_mut() = Some(state | x);
        })
    }

    /// Exit a given temporary state.
    pub fn exit(x: ThreadState) {
        let state = get();
        debug_assert!(state.contains(x));
        STATE.with(|ref k| {
            *k.borrow_mut() = Some(state & !x);
        })
    }
}
<commit_msg>Eliminate the now-unnecessary internal mod in thread_state.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Supports dynamic assertions in about what sort of thread is running and
//! what state it's in.

#![deny(missing_docs)]

use std::cell::RefCell;

bitflags! {
    /// A thread state flag, used for multiple assertions.
    pub flags ThreadState: u32 {
        /// Whether we're in a script thread.
        const SCRIPT          = 0x01,
        /// Whether we're in a layout thread.
        const LAYOUT          = 0x02,

        /// Whether we're in a script worker thread (actual web workers), or in
        /// a layout worker thread.
        const IN_WORKER       = 0x0100,

        /// Whether the current thread is going through a GC.
        const IN_GC           = 0x0200,
    }
}

macro_rules! thread_types ( ( $( $fun:ident = $flag:ident ; )* ) => (
    impl ThreadState {
        /// Whether the current thread is a worker thread.
        pub fn is_worker(self) -> bool {
            self.contains(IN_WORKER)
        }

        $(
            #[allow(missing_docs)]
            pub fn $fun(self) -> bool {
                self.contains($flag)
            }
        )*
    }

    static TYPES: &'static [ThreadState] =
        &[ $( $flag ),* ];
));

thread_types! {
    is_script = SCRIPT;
    is_layout = LAYOUT;
}

thread_local!(static STATE: RefCell<Option<ThreadState>> = RefCell::new(None));

/// Initializes the current thread state.
pub fn initialize(x: ThreadState) {
    STATE.with(|ref k| {
        if let Some(ref s) = *k.borrow() {
            panic!("Thread state already initialized as {:?}", s);
        }
        *k.borrow_mut() = Some(x);
    });
    get(); // check the assertion below
}

/// Gets the current thread state.
pub fn get() -> ThreadState {
    let state = STATE.with(|ref k| {
        match *k.borrow() {
            // This is one of the layout threads, that use rayon.
            None => LAYOUT | IN_WORKER,
            Some(s) => s,
        }
    });

    // Exactly one of the thread type flags should be set.
    debug_assert_eq!(1, TYPES.iter().filter(|&&ty| state.contains(ty)).count());
    state
}

/// Enters into a given temporary state. Panics if re-entring.
pub fn enter(x: ThreadState) {
    let state = get();
    debug_assert!(!state.intersects(x));
    STATE.with(|ref k| {
        *k.borrow_mut() = Some(state | x);
    })
}

/// Exits a given temporary state.
pub fn exit(x: ThreadState) {
    let state = get();
    debug_assert!(state.contains(x));
    STATE.with(|ref k| {
        *k.borrow_mut() = Some(state & !x);
    })
}
<|endoftext|>